数组

一维数组

一维数组的声明/定义:

数据类型[] 数组名;
1 int[] array1; 
2 String[] array2;
3 Object[] array3;
 

初始化一维数组:

  1. 静态初始化一维数组:

数据由程序员指定,长度由系统根据数据个数开辟空间

例子:int[] arr = {1,2,3,4};

//表示数组大小为4

  1. 动态初始化一维数组:

长度由程序员指定,数据由系统根据数据类型赋默认值

例子:int[] arr = new int[4];

//表示数组里可以存储4个元素

应用场景:

静态初始化:当你创建数组的时候,确定数组存储哪些具体的元素,采用静态初始化

动态初始化:创建数组的时候,不确定将来数组存储哪些数据,随着代码的运行才知道存储的具体数据预先分配内存空间

数组特性:

  1. java中的数组是一种引用数据类型,数组父类是object

例如:int[] arr = 0x123; "int[]" 这整个是引用数据类型,是数组arr的类型,而"int"是数组元素的类型,所以arr里面的元素是 "int" 基本数据类型

  1. 数组是一个容器,可以同时容纳多个元素(数组是一个数据的集合)

  2. 数组当中可以存储基本数据类型的数据,也可以存储引用数据类型的数据

1  int[] arr = {1,2,3,4};//数组存储的基本数据类型
2  String[] array = {"aaa","bbb","ccc"};//数组存储的引用数据类型
  1. 数组因为是引用类型,所以数组对象存储在堆内存中(数组存储在堆内存中)

  2. 数组当中如果存储的是"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  }
  1. 数组一旦创建,在java中规定,长度不可变(数组长度不可变)

  2. 数组的分类:一维数组、二维数组、三维数组、多维数组...

  3. 所有的数组对象都有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  }
  1. java中的数组要求数组中元素的类型统一,例如:int类型数组只能存储int类型

  2. 数组中每一个元素都是有下标的,下标从0开始,以1递增,最后一个元素的下标:length - 1

    注意:我们对数组元素进行“存取”的时候,都需要通过下标来进行(下标非常重要),使用下标时,下标不能超过数组长度,也不能是负数,否则会出现数组下标越界异常(ArrayIndexOutOfBoundsException)

  3. 数组在内存方面存储的时候,数组中的元素内存地址是连续的(存储的每一个元素都是有规则的,挨着排列)。内存地址连续,这是数组存储元素的特点,数组实际上是一种简单的数据结构

  4. 数组首元素的内存地址作为整个数组对象的内存地址(数组的第一个元素地址就是数组的元素地址)

    为什么拿数组首元素的内存地址作为这个数组对象的内存地址?

    原因::因为数组在存储元素的时候内存地址是连续的

数组的优点和缺点:

优点:

查询/查找/检索某个下标上的元素时效率极高,可以说是查询效率最高的一个数据结构

为什么检索效率高?

  1. 数组元素在空间存储上,内存地址是连续的。

  2. 每一个元素类型相同,所以占用的空间大小一样

  3. 知道第一个元素的内存地址,知道每一个元素占用的空间大小,又知道下标(知道下标就知道偏移量),通过一个数学表达式,就可以快速计算出某个下标位置上元素的内存地址,直接通过内存地址定位,效率非常高。

缺点:

  1. 随机增删效率较低,数组无法存储大数据量,因为随机增删元素会涉及到后面的元素统一向前或者向后的操作

    注意:对于数组中最后一个元素的增删,是没有效率影响

  2. 数组不能存储大数据量的

    原因:因为很难在内存空间上找到一块特别大的连续的内存空间

把数组传入方法中的传法:

  1. 方式1

1 int[] a = {1,2,3};
2   printArray(a);
  1. 方式2

 printArray(new int[]{1,2,3});
  1. 方式3

1  int[] a = new int[4];
2  printArray(a);
3  printArray(new int[4]);

关于一维数组的扩容:

java中对数组的扩容是:先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中

注解:数组扩容效率较低。因为涉及到拷贝的问题。所以在以后的开发中请注意:尽可能少的进行数组的拷贝。可以在创建数组对象的时候预估计以下多长合适,最好预估准确,这样可以减少数组的扩容次数。提高效率。

数组扩容的三种方法:

  1. 使用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开始接受旧数组拷贝的元素
  1. 使用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;//把扩容后的数组内存地址赋值给原来的数组
  1. 使用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;

二维数组的初始化:

  1. 静态初始化

    int[][] array = {{1,2,3},{2,3,4,5},{3,4,5,6},{7,8,9,10}};
  2. 动态初始化

    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 }
posted @ 2020-12-12 10:00  想变强的菜鸟  阅读(82)  评论(0编辑  收藏  举报