Java中的数组
一维数组
1、Java语言中的数组是一种引用数据类型。不属于基本数据类型。数组的父类是object。
2、数组实际上是一个容器,可以同时容纳多个元素。( 数组是一个数据的集合。)
数组:字面意思是“一组数据”
3、数组当中可以存储“基本数据类型”的数据,也可以存储“引用数据类型”的数据。
4、数组因为是引用类型,所以数组对象是堆内存当中。( 数组是存储在堆当中的)
5、数组当中如果存储的是“java对象”的话,实际上存储的是对象的“引用(内存地址)”,数组中不能直接存储java对象。
6、数组一旦创建,在java中规定,长度不可变。(数组长度不可变)
7、数组的分类:一维数组、 二维数组、 三维数组、多维数组… ( 一维数组较多,二维数组偶尔使用 )
8、所有的数组对象都有length属性(java自带的) ,用来获取数组中元素的个数。
//创建一个数组
int[] s={23,4,53,654,22};
//可以使用length属性来获取元素个数
int unm=s.length;//5个
9、java 中的数組要求数组中元素的类型统一。 比如int类型数组只能存储int类型, String类型数组只能存储String类型。
例如:超市购物,购物袋中只能装苹果,不能同时装苹果和橘子。( 数组中存储的元素类型统一)
10、数组在内存方面存储的时候,数组中的元素内存地址是连续的。
11、所有的数组都是拿“第一个小方框的内存地址”作为整个数组对象的内存地址。(详情看上面数组内存图)
(数组中首元素的内存地址作为整个数组对象的内存地址。)
12、数组中每一个元素都是有下标的,下标从0开始,以1递增。最后一个元素的下标是: length - 1
下标非常重要,因为我们对数组中元素进行“存取”的时候,都需要通过下标来进行。
//动态初始化一个数组
int[] x=new int[5];//数组开辟了五个内存空间,初始值都为0
//为数组赋值
int[0]=6;
int[1]=13;
...
//静态初始化一个数组
int[] s={3,54,22,54,65};
//下标从0开始,取出数组的元素
int a=int[0];//3
int b=int[1];//54
int c=int[2];//22
...
13、一维数组的静态初始化和动态初始化
//静态初始化:
int[] arr = {1,2,3,4};
Object[] objs = {new Object(), new Object(), new Object()};
//动态初始化:
int[] arr = new int[4]; // 4个长度,每个元素默认值0
Object[] objs = new Object[4]; // 4个长度,每个元素默认值null
//数组的遍历
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
二维数组
1、二维数组跟一维数组并无太大区别,二维数组就是一个数组中存储了多个一维数组的数组
直接上代码
//二维数组的静态初始化和动态初始化
//静态初始化:
int[][] arr = {{1,2,34},
{54,4,34,3},
{2,34,4,5}
};
Object[][] arr = {
{new Object(),new Object()},
{new Object(),new Object()},
{new Object(),new Object(),new Object()}
};
//动态初始化:
int[][] arr = new int[3][4];
Object[][] arr = new Object[4][4];
Animal[][] arr = new Animal[3][4];
// Person类型数组,里面可以存储Person类型对象,以及Person类型的子类型都可以。
Person[][] arr = new Person[2][2];
....
//二维数组的遍历
// 外层for循环负责遍历外面的一维数组。
for(int i = 0; i < arr.length; i++){
// 里面这个for循环负责遍历二维数组里面的一维数组。
for(int j = 0; j < arr[i].length; j++){
System.out.print(arr[i][j]);
}
// 换行。
System.out.println();
}
总结
说了这么多,数组的性质已经了解了
数组这种数据结构的优点和缺点是什么?
优点:
1、查询/查找/检索某个下标上的元素时效率极高。可以说是查询效率最高的一个数据结构。
2、为什么检索效率高?
- 每一个元素的内存地址在空间存储上是连续的。
- 每一个元素类型相同,所以占用空间大小一样。
- 知道第一个元素内存地址,知道每一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址。直接通过内存地址定位元素,所以数组的检索效率是最高的。
3、数组中存储100个元素,或者存储100万个元素,在元素查询/检索方面,效率是相同的,
因为数组中元素查找的时候不会一个一个找,是通过数学表达式计算出来的。( 算出一个内存地址,直接定位的。)
缺点:
1、由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候,效率较低,因为随机增删元素会涉及到后面元素统-向前或者向后位移的操作。
2、数组不能存储大数据量,为什么?
因为很难在内存空间上找到-块特别大的连续的内存空间。
注意:对于数组中最后一个元素的增删,是没有效率影响的。
扩展:
关于-维数组的扩容。
在java开发中,数组长度一旦确定不可变,那么数组满了怎么办?
数组满了,需要扩容。
java中对数组的扩容是:
先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中。
使用System.arraycopy()方法
//拷贝源(从这个数组中拷贝)
int[] src = {1, 11,22,3, 4};
//拷贝目标(拷贝到这个目标数组上)
//动态初始化一个长度为20的数组,每一个元素默认值0
int[] dest = new int[20];
//调用JDK System类 中的arraycopy方法,来完成数组的拷贝
//System. arrgycopy(src, 1, dest, 3, 2);
//逼历目标数组
for (int i = 0; i < dest.length; i++) {
System. out . println(dest[i]); // θ θ θ 11 22 ... θ
}
//5个参数,第一个是拷贝源,第二个是开始拷贝的位置
//第三是拷贝目标,第四个是从哪个位置开始接收,第五个是
//从拷贝源中拷贝多少
System. arraycopy(src,0, dest,0, src.1ength);
结论:数组扩容效率较低。因为涉及到拷贝的问题。所以在以后的开发中请注意:尽可能少的进行数组的拷贝。
可以在创建数组对象的时候预估计以下多长合适,最好预估准确,这样可以减少数组的扩容次数。提高效率。