目录
在JAVA语言中数组是一种数据结构,是用来存储同一类型数据的集合或者序列,我们可以通过整型下标(index,异或索引)去访问或遍历数组中的任意值。例如a是一个整型数组,a[i]就是访问树祖宗下标为i的元素;
我们想要使用数组这一数据结构就需要提前声明数组,在Java中声明数组有三种方式(以整型数组为例);
- /*方式一*/
- int[] arr = {1,2,3,4,5};
- /*方式二*/
- int[] arr = new int[]{1,2,3,4,5};
- /*方式三*/
- int[] arr = new int[5];
- arr[0]=1; arr[1]=2; arr[2]=3; arr[3]=4; arr[4]=5;
其中第一、二种,是你预先知道数组的内容,而第三种都是你先创建爱你长度为5的数组,然后逐一复制;这里有一个小细节,不能在给定初始值的同时设置长度,即一下格式不允许:
在不同类型的数组在没有为元素赋值之前,数组中的元素都是由默认值的,整型数组默认值为0、boolean类型数组默认值为false、对象类型数组默认值为null;
在内存层面数组类型和基本类型有所不同,基本类型在内存中只对应一块空间,但是数组有两块:一块用来存储数组内容本身,另一块用来存储内容的位置也就是地址值(首元素arr[0]的地址值),为什么会这样呢?我们看如下代码:(这串代码是可运行的)
- int[] arrA = {1,2,3};
- int[] arrB = {1,2,3,4};
- arrA = arrB;
这段代码中,arrA初始的长度是3,arrB的长度是4,将arrB的值赋给了arrA。如果arrA对应的内存空间是直接存储的数组内容,那么它将没有足够的空间去容纳arrB的所有元素。
用两块空间存储就简单得多,arrA存储的值就变成了和arrB的一样,存储的都是数组内容(4,5,6,7)的地址,此后访问arrA就和arrB是一样的了,而arrA (1,2,3)的内存空间由于不再被引用会进行垃圾回收;
由此可以看出,给数组变量赋值和给数组中元素赋值是两回事,给数组中元素赋值是改变数组内容,而给数组变量赋值则会让变量指向一个不同的位置(指向首元素的地址)。
上面我们说数组的长度是不可以变的,不可变指的是数组的内容空间,一经分配,长度就不能再变了,但可以改变数组变量的值,让它指向一个长度不同的空间,就像上例中arrA后来指向子arrB一样。
对数组进行操作的辅助类,实现了对数组的常用操作。
sort 方法:可以对数组排序,默认数组数值从小到大排列,用户可以自定义排列顺序,
Arrays.sort(arr);
copyOf/copyOfRange 方法:复制数组。底层调用 System.arrayCopy 的本地方法实现,常用于数组扩容。
- int[] arr1 = Arrays.copyOf(arr, 10); // 复制数组:前 10 个单位
- int[] arr2 = Arrays.copyOf(arr, 0, arr.length); // 复制数组:从 0 到 arr.length - 1
asList 方法:将数组转化为列表(List 类),但数组数据必须是包装类型。
调用该方法将数组转换为列表后,在内存中实际还是以数组形式存储。这可能会导致以下两个问题:
- arr[] = new Integer[]{1, 2, 3, 4}; // 数组必须是包装数据类型
- List list = Arrays.asList(arr); // 将数组转换为集合(有问题)
- List list = new ArrayList<>(Arrays.asList(arr)); // 将数组转换为集合(推荐)
Java中其实是没有二维数组的,只不过java的一维数组可以看成是一个对象,那么这样我们就可以将几个一维数组当做元素(对象)存储到另一个一维数组中就得到了我们要的二维数组。
二维数组的元素个数 = 二维数组中一维数组(元素)的个数 = arr.length;
二维数组的每个元素是一维数组, 所以如果需要得到每个一维数组中的元素,还需要再次遍历;因为第一次我们得到的只是一个对象,想要具体值还要继续遍历;
语法格式
int[][] 名称 = new int[行数][列数];
示例: 以下三种方式都正确;
- int[][] arr = new int[2][3];
- int[][] arr = new int[3][];
- int[][] arr = {{1,2,3}, {4,5}, {5,6,7,8}};