- 一、数组概述
- 二、数组的声明与创建
- 2.1 数组的声明
- 2.2 数组的创建
- 三、数组使用
- 3.1 Java 内存(简要分析)
- 3.1.1 堆
- 3.1.2 栈
- 3.1.3 方法区
- 3.2 初始化
- 3.2.1 静态初始化
- 3.2.2 动态初始化
- 3.3 数组的基本特点
- 3.4 For-Each 循环
- 3.5 数组作为方法参数
- 四、多维数组
- 4.1 初始化
- 4.1.1 静态初始化
- 4.1.2 动态初始化
- 1. 直接为每一维分配空间
- 2. 从最高维开始,分别为每一维分配空间
- 五、Arrays 类
- 六、稀疏数组
- 6.1 稀疏数组引入
- 6.2 稀疏数组介绍
- 数组是固定大小的相同类型数据的有序集合。
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
- 数组中的每一个数据被称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
quad 首先,必须声明数组变量,才能在程序中使用数组。声明数组变量的语法:dataType[] arrayRefVar;或 dataType arrayRefVar[];,其中 dataType 为数据类型,arrayRefVar 为数组变量名。
quad 注:建议使用 dataType[] arrayRefVar 的声明风格声明数组变量。dataType arrayRefVar[] 风格是来自 C/C++ 语言 ,在 Java 中采用是为了让 C/C++ 程序员能够快速理解 Java 语言。
2.2 数组的创建-
Java 语言使用 new 关键字来创建数组,语法:arrayRefVar = new dataType[arraySize];。这个语句做了两件事:
- 使用 dataType[arraySize] 创建了一个数组,其中 arraySize 为数组长度,即数组可以存储数据的最大数量。
- 把新创建的数组的引用赋值给变量 arrayRefVar。
-
你还可以使用直接赋值数组的方式创建数组:dataType[] arrayRefVar = {value0, value1, ..., valuek};,其中 value0, value1, ..., valuek 为数组中存储的数据。
-
数组的声明和创建可以用一条语句完成:dataType[] arrayRefVar = new dataType[arraySize];
quad 数组的元素是通过索引访问的。数组索引从 0 开始,所以索引值从 0 到 arrayRefVar.length-1,其中 arrayRefVar.length 返回数组的长度。如果索引不在 [0,arrayRefVar.length-1] 范围,则报 ArrayIndexOutOfBoundsException 数组下标越界异常。
3.1 Java 内存(简要分析)
quad
数组在 Java 内存存储的情形大致如下:
- 存放 new 的对象和数组。
- 可以被所有的线程共享,不会存放别的对象引用。
- 存放基本变量类型(会包含这个基本类型的具体数值)
- 存放引用对象的变量(会存放这个引用在堆里面的具体地址)
- 存放所有的 class 和 static 变量。
- 可以被所有的线程共享
quad Java 数组必须先初始化,然后才可以被使用。所谓初始化就是为数组的数组元素分配内存空间,并为每个数组元素赋初始值。
3.2.1 静态初始化- 初始化时由开发人员显式地指定每个数组元素的初始值,由 JVM 决定数组的长度。
- 示例:int[] array = {10,20,30,40,50,60,70,80,90};
- 初始化时由开发人员指定数组的长度,由 JVM 初始化每个数组元素的默认值。
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
- 示例:double[] array = new double[10]; 默认值:0.0。
- 数组长度是固定的。数组一旦被创建,它的大小就是不可以被改变的。
- 数组中的元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属于引用类型,可以被看成对象,数组中的每个元素相当于该对象的成员变量。
- 数组本身就是对象,Java 中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
- JDK 1.5 引进了一种新的循环类型,被称为 For-Each 循环或者增强型 for 循环,它能在不使用下标的情况下遍历数组。(点此了解)
- 示例:foreach 循环遍历数组并打印
public class Demo01 { public static void main(String[] args) { // 初始化数组 int[] array = {10,20,30,40,50,60,70,80,90}; // foreach循环 for (int num : array) { System.out.println(num); } } }
- 数组可以作为参数传递给方法。
- 数组可以作为返回值返回给方法。
- 示例:找出一个数组的最大值与最小值,并以数组形式返回。
public class Demo02 { public static void main(String[] args) { double[] array = new double[100]; // 为数组赋值随机数 for (int i = 0; i < array.length; i++) { array[i] = Math.random() * 100; // 每五个数字换一行 if (i != 0 && i % 5 == 0){ System.out.println(); } System.out.print(array[i]+"t"); } double[] minMax = minMax(array); System.out.println("nt数组的最小值为:"+minMax[0]+",最大值为:"+minMax[1]); } // 找出数组中的最大值与最小值 public static double[] minMax(double[] array) { double min = array[0];// 假设数组第 0 个元素为最小值 double max = array[9];// 假设数组第 9 个元素为最大值 for (double num : array) { if (min > num) {// 找到数组最小值 min = num; } if (max < num) {// 找到数组最大值 max = num; } } return new double[]{min,max}; } }
quad 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。注:多维数组的每个数组元素的长度可以不一致。
quad 多维数组与一维数组相同,都是通过索引对元素进行访问的。以二维数组为例:array[2][3]即访问 array 数组第 2 行第 3 列的元素。
4.1 初始化 4.1.1 静态初始化- 声明数组的同时使用大括号直接对数组赋值。
- 以二维数组为例:int[][] array = {{1,2,3},{4,5,6},{7,8,9}},此语句声明了一个 3 行 3 列的二维数组。
- 注:多维数组的每个数组元素的长度可以不一致,例:int[][] array = {{1},{2,3},{4,5,6}};
- 格式:type[][]...[] arrayName = new type[length1][length2]...[lengthN];其中 type 可以为基本数据类型和引用数据类型,length1、length2、… 、lengthN 必须为正整数。
- 二维数组:type[][] arrayName = new type[rowLength][columnLength];其中 rowLength 表示行长度,columnLength 表示列长度。
- 示例:int[][] array = new int[3][3];
- 首先为最高维分配引用空间,也就是为最高维能保存数据的最大长度,然后再为其每个数组元素单独分配空间。
- 示例:
public class Demo04 { public static void main(String[] args) { int[][] numArray = new int[2][]; numArray[0] = new int[3]; numArray[0][0] = 1; numArray[0][1] = 2; numArray[0][2] = 3; numArray[1] = new int[]{4,5,6,7,8}; for (int[] array : numArray) { for (int num : array) { System.out.print(num + ","); } System.out.println(); } } }
- 由于数组对象本身并没有什么方法可以供我们调用,但 API 中提供了一个工具类 Arrays 供我们使用,从而可以对数组对象进行一些基本的 *** 作。
- Arrays 类中的方法都是 static 修饰的静态方法,在使用的时候可以直接使用类名进行调用,而 “不用” 使用对象来调用(注意:是 “不用” 而不是 “不能”)
- Arrays 类常用方法:(array 表示数组变量)
- Arrays.toString(array):返回指定数组 array 内容的字符串表示形式。
- Arrays.fill(array,[ int fromIndex, int toIndex,] dataType val):将指定的 dataType 类型的 val 值分配给指定的 array 数组的指定范围的每个元素。注意事项:
- dataType 要与 array 数组的类型相同。
- [ int fromIndex, int toIndex,] 为可选。
- Arrays.equals(dataType[] array1,[ int aFromIndex, int aToIndex,] dataType[] array2[, int bFromIndex, int bToIndex]):比较两个数组 array1、array2 在指定范围内是否相等。注意事项:
- [ int aFromIndex, int aToIndex,] 与 [, int bFromIndex, int bToIndex] 为可选。
- Arrays.copyOf(dataType[] original, int newLength):从原数组 original 复制指定长度 newLength 的数组到新的数组对象。
- Arrays.sort(dataType[] array[, int fromIndex, int toIndex]):按升序排列数组的指定范围。注意事项:
- [, int fromIndex, int toIndex] 为可选。
- Arrays.binarySearch(dataType[] array, int fromIndex, int toIndex, dataType key):使用二分查找算法在给定数组 array 中搜索给定值的对象 key。
- 数组在调用前必须排序好。
- 如果查找值 key 包含在数组 array 中,则返回搜索键的索引;否则返回 (-(插入点)-1),插入点是索引键 key 将要插入数组的那一点,即第一个大于该键的元素索引。
- 需求:编写五子棋游戏中,有存储棋局退出和继续上一棋局的功能。
- 分析问题:因为该二维数组的很多值是默认值 0,因此记录了很多没有意义的数据。
- 解决:稀疏数组。
- 当一个数组中大部分元素为 0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
- 稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值。
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模。
- 如下图:左边是原始数组,右边是稀疏数组。
- 五子棋游戏的棋盘数组转为稀疏数组:
- 示例:将五子棋棋盘使用稀疏数组保存。
public class Demo06 { public static void main(String[] args) { // 创建一个二维数组 11 * 11。其中,0:没有棋子,1:白棋,2:黑棋 int[][] array = new int[11][11]; array[1][2] = 1; array[2][3] = 2; // 打印原始数组 printArray(array,"原始数组:"); // 获取非零元素个数 int num = nonZero(array); // 原始数组转为稀疏数组 int[][] sparseArray = originalToSparse(array, num); printArray(sparseArray,"稀疏数组:"); // 稀疏数组转为原始数组 int[][] originalArray = sparseToOriginal(sparseArray); printArray(originalArray,"原始数组:"); } // 获取原始数组非零元素个数 public static int nonZero(int[][] originalArray) { int num = 0; for (int[] numArray : originalArray) { for (int i : numArray) { if (i != 0) { num++; } } } System.out.println("一共有 "+num+" 个有效数字"); return num; } // 稀疏数组转换为原始数组 public static int[][] sparseToOriginal(int[][] sparseArray) { int[][] originalArray = new int[sparseArray[0][0]][sparseArray[0][1]]; for (int i = 1; i < sparseArray.length; i++) { originalArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2]; } return originalArray; } // 原始数组转换为稀疏数组 public static int[][] originalToSparse(int[][] array, int num) { int[][] sparseArray = new int[num+1][3]; int line = 0; sparseArray[line] = new int[]{array.length, array.length, num}; for (int i = 0; i < array.length; i++) { for (int j = 0; j < array[i].length; j++) { if (array[i][j] != 0 && line < num) { sparseArray[++line] = new int[]{i,j,array[i][j]}; } } } return sparseArray; } // 打印数组 public static void printArray(int[][] array, String str) { System.out.println(str); for (int[] numArray : array) { for (int i : numArray) { System.out.print(i+"t"); } System.out.println(); } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)