数组
一维数组的声明/定义:
数据类型[] 数组名;
1 int[] array1;
2 String[] array2;
3 Object[] array3;
初始化一维数组:
-
静态初始化一维数组:
数据由程序员指定,长度由系统根据数据个数开辟空间
例子:int[] arr = {1,2,3,4};
//表示数组大小为4
-
动态初始化一维数组:
长度由程序员指定,数据由系统根据数据类型赋默认值
例子:int[] arr = new int[4];
//表示数组里可以存储4个元素
应用场景:
静态初始化:当你创建数组的时候,确定数组存储哪些具体的元素,采用静态初始化
动态初始化:创建数组的时候,不确定将来数组存储哪些数据,随着代码的运行才知道存储的具体数据预先分配内存空间
数组特性:
-
java中的数组是一种引用数据类型,数组父类是object
例如:int[] arr = 0x123; "int[]" 这整个是引用数据类型,是数组arr的类型,而"int"是数组元素的类型,所以arr里面的元素是 "int" 基本数据类型
-
数组是一个容器,可以同时容纳多个元素(数组是一个数据的集合)
-
数组当中可以存储基本数据类型的数据,也可以存储引用数据类型的数据
1 int[] arr = {1,2,3,4};//数组存储的基本数据类型 2 String[] array = {"aaa","bbb","ccc"};//数组存储的引用数据类型
-
数组因为是引用类型,所以数组对象存储在堆内存中(数组存储在堆内存中)
-
数组当中如果存储的是"java对象"的话,实际上存储的是对象内存地址
例子:
1 //定义一个学生类 2 public class Student{ 3 private String name; 4 private int age; 5 public Student() {} 6 public Student(String name, int age) { 7 this.name = name; 8 this.age = age; 9 } 10 public String getName() { 11 return name; 12 } 13 public void setName(String name) { 14 this.name = name; 15 } 16 public int getAge() { 17 return age; 18 } 19 public void setAge(int age) { 20 this.age = age; 21 } 22 } 23 24 public class Test { 25 public static void main(String[] args) { 26 //初始化数组 stu为"Student[]"类型的数组(引用数据类型), 27 Student[] stu = new Student[2]; 28 stu[0] = new Student("aaa",15); //stu[0]中存储的是在堆中new student学生对象的内存地址 29 stu[1] = new Student("bbb",18); //stu[1]也是存储地址 30 } 31 32 }
-
数组一旦创建,在java中规定,长度不可变(数组长度不可变)
-
数组的分类:一维数组、二维数组、三维数组、多维数组...
-
所有的数组对象都有length属性(java自带的),用来获取数组中元素的个数
1 public class Test { 2 public static void main(String[] args) { 3 int[] arr = new int[4]; 4 int[] arr1 = {1,2,3,4,5,6}; 5 System.out.println("arr数组长度为:"+arr.length);//4 6 System.out.println("arr1数组长度为:"+arr1.length);//6 7 } 8 9 }
-
java中的数组要求数组中元素的类型统一,例如:int类型数组只能存储int类型
-
数组中每一个元素都是有下标的,下标从0开始,以1递增,最后一个元素的下标:length - 1
注意:我们对数组元素进行“存取”的时候,都需要通过下标来进行(下标非常重要),使用下标时,下标不能超过数组长度,也不能是负数,否则会出现数组下标越界异常(ArrayIndexOutOfBoundsException)
-
数组在内存方面存储的时候,数组中的元素内存地址是连续的(存储的每一个元素都是有规则的,挨着排列)。内存地址连续,这是数组存储元素的特点,数组实际上是一种简单的数据结构
-
数组首元素的内存地址作为整个数组对象的内存地址(数组的第一个元素地址就是数组的元素地址)
为什么拿数组首元素的内存地址作为这个数组对象的内存地址?
原因::因为数组在存储元素的时候内存地址是连续的
优点:
查询/查找/检索某个下标上的元素时效率极高,可以说是查询效率最高的一个数据结构
为什么检索效率高?
-
数组元素在空间存储上,内存地址是连续的。
-
每一个元素类型相同,所以占用的空间大小一样
-
知道第一个元素的内存地址,知道每一个元素占用的空间大小,又知道下标(知道下标就知道偏移量),通过一个数学表达式,就可以快速计算出某个下标位置上元素的内存地址,直接通过内存地址定位,效率非常高。
-
随机增删效率较低,数组无法存储大数据量,因为随机增删元素会涉及到后面的元素统一向前或者向后的操作
注意:对于数组中最后一个元素的增删,是没有效率影响
-
数组不能存储大数据量的
把数组传入方法中的传法:
-
方式1
1 int[] a = {1,2,3}; 2 printArray(a);
-
方式2
printArray(new int[]{1,2,3});
-
方式3
1 int[] a = new int[4]; 2 printArray(a); 3 printArray(new int[4]);
关于一维数组的扩容:
java中对数组的扩容是:先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中
注解:数组扩容效率较低。因为涉及到拷贝的问题。所以在以后的开发中请注意:尽可能少的进行数组的拷贝。可以在创建数组对象的时候预估计以下多长合适,最好预估准确,这样可以减少数组的扩容次数。提高效率。
数组扩容的三种方法:
-
使用System.arraycopy(5个参数);进行数组扩容
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
底层使用的是c++
第一个参数为源(旧)数组,第二个参数为源(旧)数组下标从哪开始拷贝。第三个参数为目标(新)数组,第四个参数为从目标(新)数组哪个下标开始拷贝源(旧)数组元素,第五个参数从源(旧)数组中拷贝多少个元素
1 //旧数组 2 int[] src = {1, 11, 22, 3, 4}; 3 //定义新数组 4 int[] dest = new int[20]; 5 //拷贝扩容 6 System.arraycopy(src, 0, dest, 0, src.length); 7 //从旧数组下标0开始拷贝,拷贝长度为旧数组长度大小,新数组从下标0开始接受旧数组拷贝的元素
-
使用Arrays数组工具类扩容Arrays.copyOf(original, newLength)
original需要进行扩容的数组,newLength,需要数组的容量
copyOf()方法底层使用的是System.arraycopy()方法
1 //定义 2 String[] names = {"aaa","bbb","ccc","ddd"}; 3 //调用Arrays数组工具类的copyOf方法进行扩容 扩容为原来数组的1.5倍 4 newNames = Arrays.copyOf(names,(names.length + (names.length>>1))); 5 names = newNames;//把扩容后的数组内存地址赋值给原来的数组
-
使用for循环,手写扩容步骤
1 //旧数组 2 int[] arrays = {1,2,3,4,5,6}; 3 //新数组,容量为旧数组容量的1.5倍 4 int[] newArrays = new int[arrays.length + (arrays.length >>1)]; 5 //把旧数组的元素全部转移到新数组中 6 for (int i = 0; i < arrays.length; i++) { 7 newArrays[i] = arrays[i]; 8 } 9 //把新数组的内存地址赋值给旧数组 10 arrays = newArrays;
注解:当数组存储的元素的是引用数据类型,当数组拷贝的元素是对象时,拷贝的是对象的内存地址
二维数组
二维数组的声明/定义:
1 数据类型[][] 数组名; 2 int[][] arrays1; 3 String[][] array2; 4 Object[][] array3;
二维数组的初始化:
-
静态初始化
int[][] array = {{1,2,3},{2,3,4,5},{3,4,5,6},{7,8,9,10}};
-
动态初始化
int[][] array = new int[2][3]; //两个一维数组,每个一维数组里有三个元素
注解:二维数组其实是一个特殊的一维数组,特殊在这个二维数组当中的每一个元素是一个一维数组
关于二维数组中元素的:读和改
1 array[二维数组中的一维数组的下标][一维数组的下标]; 2 array[0][0]:表示第1个一维数组中的第1个元素。 3 array[3][20]:表示第4个一维数组中的第21个元素。
遍历二维数组
1 int[][] array = {{1,2,3},{2,3,4,5},{3,4,5,6},{7,8,9,10}}; 2 for(int i = 0; i < array.length; i++){ // 外层循环4次。(负责循环二维数组中的一维数组个数) 3 int[] 一维数组 = array[i]; 4 // 负责遍历一维数组中的元素个数 5 for(int j = 0; j < 一维数组.length; j++){ 6 System.out.print(一维数组[j] + " "); 7 } 8 // 输出换行符 9 System.out.println(); 10 } 11 //变换代码之后 12 for(int i = 0; i < array.length; i++){ // 外层循环4次(负责循环二维数组中的一维数组个数) 13 for(int j = 0; j < array[i].length; j++){ 14 System.out.print(array[i][j] + " "); 15 } 16 System.out.println(); 17 }