文章目录
数组:Array
1、数组相关基础知识
- 1、Java语言中的数组是一种引用数据类型。不属于基本数据类型。数组的父类是Object。
- 2、数组实际上是一个容器,可以同时容纳多个元素。(数组是一个数据的集合)。
数组:字面意思是“一组数据”。 - 3、数组当中可以存储基本数据类型的数据,也可以存储“引用数据类型” 的数据。
- 4、数组因为是引用类型,所以数组对象是堆内存当中的。(数组是存储在堆当中的)。
- 5、数组当中如果存储的是“java对象” 的话,实际上存储的是java对象的“引用(内存地址)”,数组不能直接存储java对象。
- 6、数组的分类:一维数组、二维数组、三维数组、多维数组…(一维数组较多,二维数组偶尔使用)。
- 7、数组一旦创建,在java规定,长度不可变。(数组长度不可变)。
- 8、所有数组对象都有length属性(java自带的),用来获取数组中元素的个数。
- 9、java中的数组要求数组中的元素类型统一。
- 10、数组在内存方面存储的时候,数组中的元素内存地址(存储的每一个元素都是有规则的挨着排列的)是连续的。内存地址连续。这是数组存储元素的特点。数组实际上是一种简单的数据结构。
- 11、所有的数组都是拿“第一个小方框的内存地址”作为整个数组对象的内存地址。(数组中首元素的内存地址作为整个数组对象的内存地址)
- 12、数组中的每一个元素都是有下标的,下标从0开始,以1递增。最后一个元素的下标:length - 1
下标非常重要,因为我们对数组中的元素进行“存取”的时候都需要下标;来进行。
2、数组的优缺点
优点:
查询、检索某个下标上的元素时效率极高。可以说查询效率最高的一个数据结构。
为什么检索效率高?
- 第一:每一个元素的内存地址在空间存储上是连续的。
- 第二:每一个元素类型相同,所以占用空间大小一样。
- 第三:如果知道一个元素内存地址,知道每一个元素占用空间大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上的元素的内存地址。直接通过内存地址定位元素,所以数组的检索效率是最高的。
缺点:
- 第一:由于为了保证数组中每个元素的内存地址连续,所以在数组上随即删除或者增加元素的时候效率较低,因为随机增删元素会涉及到后面元素统一向前或者向后位移的操作。
- 第二:数组不能存储大量数据,因为很难在空间上找到一块特别大的连续的内存
注意:对于数组中最后一个元素的增删是没有效率影响的
一维数组
1、怎样声明一个一维数组
语法格式:
int[] array;
double[] array;
boolean[] array;
String[] array;
Object[] array;
2、怎样初始化一个一维数组呢?
包括两种方式:静态初始化一维数组、动态初始化一维数组
静态初始化一维数组:int[] array = {100,200,300};
、String[] str = {"as","cs" ,"ds"};
也可以使用 int array[] = {1,2,3}
,这是C++风格,不建议在java中使用
动态初始化一维数组:
int[] array = new int [5];
这里的5表示数组元素个数,初始化一个5个长度的int类型数组,每个元素默认值为0
String[] names = new String[6];
初始化6个长度的String类型数组,每个元素默认值null
3、对一维数组中的元素访问
public class ArrayTest01 {
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
//取(读)
System.out.println(a.length);
System.out.println("第一个元素是" + a[0]);
System.out.println("最后一个元素是" + a[4]);
System.out.println("最后一个元素是" + a[a.length - 1]);
//存(改)
a[0] = 0;//把第一个元素修改
a[a.length-1] = 999;//把最后一个元素修改
System.out.println("第一个元素是" + a[0]);
System.out.println("最后一个元素是" + a[4]);
System.out.println("最后一个元素是" + a[a.length - 1]);
}
}
输出结果:
4、 一维数组的遍历
遍历写法:
提示:下标越界会出现异常:
接上面代码
for (int i = 0;i < a.length; i++){
System.out.println(a[i]);
}
//颠倒遍历
for (int i = a.length - 1;i >= 0; i--){
System.out.println("颠倒顺序输出-->" + a[i]);
}
结果:
5、静态存储Object类
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
Object[] object= {o1,o2,o3};
/*或
Object[] object= {new Object(),new Object(),new Object()};
*/
for(int i = 0; i < object.length; i++){
System.out.println(object[i]);
}
6、动态初始化一维数组
public class ArrayTest {
public static void main(String[] args) {
//声明定义一个数组,采用动态初始化的方式创建
int[] a = new int[4];//创建长度为4的int数组,数组中每个元素的默认值为0
//遍历数组
for (int i = 0; i < a.length; i++){
System.out.println("数组中的下标为" + i +"的元素是" + a[i]);
}
}
}
输出结果:
7、什么时候采用静态初始化方法/动态初始化方法?
当你创建数组的时候,确定数组中存储哪些具体的元素的时候,采用静态初始化。
当你创建数组的时候,不确定数组中存储哪些数据,你可以采用动态初始化的方式,预先分配内存空间。
8、方法的参数为数组
public class ArrayTest {
public static void main(String[] args) {
//调用方法时传一个数组
int[] a = {1,2,3,4};
printArray(a);
//不能printArray({1,2,3});没有这个语法
/* 或
printArray(new int[] {1,2,3});
*/
}
public static void printArray(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.println( array[i]);
}
}
}
9、数组中存储引用数据类型
对于数组来说,实际上只能存储java对象的“内存地址”。数组中存储的每个元素都是“引用”
提示:不能存放别的引用数据类型
如果继承该引用数据类型的数据类型可以使用该数组
public class ArrayTest2 {
public static void main(String[] args) {
Animal a1 = new Animal();
Animal a2 = new Animal();
Animal[] animals = {a1,a2};
for (int i = 0; i < animals.length; i++){
animals[i].move();
}
}
}
class Animal{
public void move(){
System.out.println("Animal move");
}
}
运行结果:
10、输出数组的方法
错误示范:System.out.println(array); //这样输出的是数组的首地址,而不能打印出数组数据
正确写法:
int[] array= {1,2,3,4,5,6};
方式一:for循环
for(int i=0;i<array.length;i++)
{
System.out.println(array[i]);
}
输出为:(自动换行格式的)
方式二:for each
for(int a:array)
System.out.println(a);
输出格式同方式一。
方式三:Arrays类中的toString方法(注意,是Arrays不是Array,Arrays类位于java.util包下)
需要导入import java.util.Arrays
包
int[] array= {1,2,3,4,5,6};
System.out.println(Arrays.toString(array));
11、数组扩容
java中对数组的扩容是:
先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数据当中。
结论:数组扩容效率较低。因为涉及到拷贝的问题。所以在以后的开发中请注意:尽可能少的进行数组的拷贝。可以在创建数组对象的时候预估计以下多长合适,最好预估准确,这样可以减少数组的扩容次数,提高效率。
第一种方法,建立一个新的数组,通过for循环来进行拷贝扩容
int[] b=new int[a.length*2];//a.length 长度;a数组的长度。即数组中数据的个数
for(int i=0;i<a.length;i++){
b[i]=a[i];
}
System.out.println(Arrays.toString(b));//这个函数就是将数组b进行遍历输出
//如果不明白遍历什么意思,建议先学习遍历后再来看此篇文章
第二种方法:固定的写法。System.Arrays.copy(a,0,b,0,a.length);
int[] c=new int[20];
System.arraycopy(a,0,c,0,a.length);
//a,需要复制的内容。第一个0(零):在a中开始复制的内容的位置
//c,要复制的载体,在这里写c就是将a中需要复制的内容赋值给c
//第二个0(零):在c中开始复制的位置
//a.length:要复制的元素量
System.out.println(Arrays.toString©);
方法三:利用函数方法直接扩容
//原理,利用Arrays中的函数进行扩容
int[] d=Arrays.copyOf(a,22);//此函数的作用就是复制a的值。定义d的长度
// Arrays.copyOf(a,22); a,需要复制的内容(a数组),22:定义d数组的长度
System.out.println(Arryas.toString(d));
}
}
12、数组拷贝
数组拷贝的方法:System.arraycopy( Object src,int srcPos,Object dest, int destPos,int length)
Object src:源数组
int srcPos:源数组起点下标
Object dest:目标数组
int destPos:目标数组起点下标
int length:拷贝的源数组的长度
数组中存储的元素是引用也可以拷贝。且拷贝的是对象的内存地址
public class ArrayTest3 {
public static void main(String[] args) {
int[] src = {1,11,22,33,44};//拷贝源
int[] dest = new int[20];//拷贝目标
for (int i = 0; i < dest.length; i++){
System.out.print(dest[i]+" ");
}
System.out.println();
System.arraycopy(src,1,dest,2,2);//进行拷贝
for (int i = 0; i < dest.length; i++){
System.out.print(dest[i]+" ");
}
}
}
运行结果: