Bootstrap

6、Java中的数组

1、数组的声明和初始化

1.1.仅声明数组

         数组的声明涉及到指定数组的类型以及数组的名称。数组的声明格式遵循固定格式。在这种情况下,数组变量被声明了,但还没有分配内存空间。这些数组变量只是引用类型变量,它们此时没有任何内存空间与之关联,尝试访问这些变量将导致NullPointerException

type[] arrayName; 或者type arrayName[];

说明:

  • type:数组元素的数据类型,可以是Java的基本数据类型(如intdouble等)或任何引用类型(如StringObject等)。
  • arrayName:数组的名称,遵循Java的标识符命名规则
  • []:是数组标识,标识这是一个数组,可以在数据类型后,也可以在变量名后面。
// 声明一个整型数组
int[] intArray; 
// 声明一个字符串数组
String strArray[]; 
// 声明一个双精度浮点型数组
double[] doubleArray; 

1.2.数组声明并初始化

        数组的初始化是为数组分配内存空间并设置初始值的过程。Java提供了几种不同的数组初始化方式。

1.2.1.使用new关键字(指定大小)

type[] arrayName = new type[size];
  • size:数组的长度,即数组将存储的元素数量。
  • 这种方式初始化数组时,所有元素都会被自动设置为其类型的默认值:数值类型为0,布尔类型为false,对象引用类型为null

1.2.2.使用{}直接指定值

type[] arrayName = {value1, value2, ..., valueN};
  • 在这种方式中,数组的长度由提供的值的数量决定,如果{}为空,则数组长度为0。

1.2.3.new关键字和{}结合

type[] arrayName = new type[size] {value1, value2, ..., valueN};
  • 这种方式结合了new关键字和花括号,既指定了数组的大小,又提供了初始值。
  • 如果提供的值的数量少于指定的大小size,那么剩余的数组元素将被自动初始化为其类型的默认值。
  • 如果提供的值的数量多于指定的大小size,编译器会报错。

      

1.3.访问和修改数组元

type element = arrayName[index]; // 访问元素
arrayName[index] = newValue; // 修改元素
int length = arrayName.length;//数组的长度
  • index:元素的索引,必须在0到arrayName.length - 1之间。
  • 每个数组都有一个length属性,它返回数组中的元素数量。

案例

        /**
         * 访问数组元素
         */
        int[] intArray = {10, 20, 30, 40, 50};
        // 数组的下标从0开始,所以访问第二个元素(索引为1)
        int secondElement = intArray[1];
        //输出: 20
        System.out.println(secondElement);
        // 数组的下标从0开始,所以访问第四个元素(索引为3)
        //输出:40
        System.out.println(intArray[3]);

        /**
         * 修改数组元素
         */
        intArray[1] = 200;
        //输出[10, 200, 30, 40, 50]
        System.out.println(Arrays.toString(intArray));

        /**
         * 获取数组的长度
         */
        int length = intArray.length;
        //输出:5
        System.out.println(length);

1.4.遍历数组

数组可以通过传统的for循环、增强型for循环(For-Each循环)进行遍历。

        /**
         * 传统 for 循环
         */
        int[] numbers = {1, 2, 3, 4, 5};
        for (int i = 0; i < numbers.length; i++) {
            System.out.println(numbers[i]);
        }

        /**
         * 增强型 for 循环(For-Each 循环)
         */
        for (int number : numbers) {
            System.out.println(number);
        }

2、二维数组

        多维数组可以看作是数组的数组。Java中的多维数组实际上是通过嵌套数组实现的。

2.1.使用new关键字声明二维数组

type[][] arrayName = new type[dimension1][dimension2]; // 对于二维数组
  • dimension1dimension2分别是数组的两个维度的大小。可以理解为一个大数组中包含着多个小数组,dimension1是大数组的长度(有几个小数组),dimension2是小数组的长度(每个小数组中有几个值)。​​
  • 这种方式初始化多维数组时,每个元素本身是一个数组,需要进一步初始化。

2.2.使用{}声明二维数组

type[][] arrayName = {
    {value11, value12},
    {value21, value22}
};

与一维数组同理理解即可

2.3.二维数组的访问与修改

        在 Java 中,二维数组可以被看作是数组的数组,即每个元素本身也是一个数组。以下是如何访问和修改二维数组的元素的示例

        int[][] matrix = {
                {1, 2, 3},
                {4, 5, 6},
                {7, 8, 9}
        };

        // 访问第二行第三列的元素6(注意数组索引从0开始)
        int element = matrix[1][2];
        System.out.println("访问的元素是: " + element);
        
        
        // 修改第二行第三列的元素,将元素 6 修改为 10
        matrix[1][2] = 10;
        // 打印修改后的二维数组
        System.out.println(Arrays.toString(matrix));

2.4.二维数组的遍历

       以下案例中使用了一个外层循环来遍历二维数组的每一行,然后使用了一个内层循环来遍历每一行中的每个元素。

        /**
         * 传统for
         */
        int[][] matrix = {
                {1, 2, 3},
                {4, 5, 6},
                {7, 8, 9}
        };

        // 外层循环遍历行
        for (int i = 0; i < matrix.length; i++) {
            // 内层循环遍历列
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println(); // 每遍历完一行后换行
        }

        /**
         * 增强型 for 循环(For-Each 循环)
         */
        // 外层循环遍历行,使用增强型 for 循环
        for (int[] row : matrix) {
            // 内层循环遍历列,使用传统 for 循环
            for (int j = 0; j < row.length; j++) {
                System.out.print(row[j] + " ");
            }
            System.out.println(); // 每遍历完一行后换行
        }

3、内存中的数组

  • 当程序执行到 int[] arr1的时候,系统会在内存开辟一块空间,变量arr1指向这个空间。
  • 之后程序开始解析等于符号右边的内容,也就是创建数组。
  • 系统根据指定的数据类型和数组的大小创建一块连续的数组空间,将值存放到空间中。
  • 最后将创建的连续的数组空间的地址存入到arr1指向的空间中,这就是赋值。
  • 如上图所示,如果将arr1赋值给arr2,其实就是将arr1指向的内存空间中存放的值(数组地址)赋值给arr2,并不是直接将数组赋值给arr2。

以上就是引用类型的内存存储大概逻辑。一个通俗的理解,并不完全严谨。

4、Arrays工具类

4.1.Arrays.asList(T... a)

  • 参数:一个可变参数列表T... a,表示要转换为列表的元素。
  • 返回值:返回一个固定大小的列表(List集合),其元素由参数中的数组元素组成。
  • 可变参数:可以传一个或多个值,多个值时(用逗号隔开)编译器会自动分装为一个数组。也可直接传数组(简单解释)。

示例

String[] strArray = {"Java", "Python", "C++"};
//获得一个list集合
List<String> list = Arrays.asList(strArray);
System.out.println(list); // 输出: [Java, Python, C++]

4.2.Arrays.toString(Object[] a)

  • 参数:一个对象数组Object[] a,表示要转换为字符串的数组。
  • 返回值:返回一个字符串,表示数组及其元素的字符串表示。

示例

Integer[] intArray = {1, 2, 3, 4, 5};
//将数组转换成一个易于阅读的字符串表示形式。
//这个方法对于打印数组内容到控制台或记录日志时非常有用
String arrayString = Arrays.toString(intArray);
System.out.println(arrayString); // 输出: [1, 2, 3, 4, 5]

4.3. Arrays.sort(Object[] a)

  • 参数:一个对象数组Object[] a,表示要排序的数组。
  • 返回值:无返回值(void),数组在原地被排序。参考《1.4、内存中的数组》

示例

        /**
         * Arrays.sort(Object[] a)
         * 默认情况下,对数组进行升序排序,即最小的元素排在最前面,最大的元素排在最后面。
         */
        String[] strArray = {"banana", "apple", "mango"};
        Arrays.sort(strArray);
        // 输出: [apple, banana, mango]
        System.out.println(Arrays.toString(strArray));

        /**
         * 要对数组进行降序排序,
         * 可以使用 Arrays.sort(Object[] a, Comparator<? super T> c) 方法,
         * 并提供一个自定义的比较器(Comparator),该比较器定义了降序排序的规则。
         */

        Arrays.sort(strArray, (a, b) -> b.compareTo(a));
        // 输出: [mango, banana, apple]
        System.out.println(Arrays.toString(strArray));

4.4. Arrays.copyOf(Object[] original, int newLength)

  • 参数:一个对象数组Object[] original,和一个新长度int newLength
  • 返回值:返回一个新的数组,其元素是original数组的复制,新数组的长度为newLength

示例

Integer[] originalArray = {1, 2, 3};
//可以将数组扩大,也可以缩小,超出的部分截取
Integer[] copiedArray = Arrays.copyOf(originalArray, 5);
// 输出: [1, 2, 3, null, null]
System.out.println(Arrays.toString(copiedArray)); 

4.5. Arrays.copyOfRange(Object[] original, int from, int to)

  • 参数:一个对象数组Object[] original,开始索引int from,结束索引int to(不包括)。
  • 返回值:返回一个新的数组,包含从fromto索引范围内的original数组元素。

示例

Integer[] originalArray = {1, 2, 3, 4, 5};
// 复制,从索引1到索引3(不包括索引3),数组的下标是从0开始 
Integer[] subArray = Arrays.copyOfRange(originalArray, 1, 3);
System.out.println(Arrays.toString(subArray)); // 输出: [2, 3]
;