数组

本文详细介绍了Java中的数组,包括数组的定义、初始化、赋值、多维数组以及Arrays类提供的实用功能。文章指出数组是尺寸固定的,强调性能,但在现代Java版本中,容器通常提供更好的灵活性和类型安全。尽管数组在特定性能场景下仍具价值,但推荐优先考虑使用容器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


数组是相同类型的、用一个标识符名称封装到一起的一个 对象序列基本类型数据序列。可以使用整型索引值访问它们的元素(“[]”语法是访问数组唯一的方式),并且它们的尺寸不能改变。

对象数组基本类型数组在使用上几乎是相同的,唯一的区别就是对象数组保存的是引用,基本类型数组直接保存基本类型的值。

数组标识符其实只是个引用,指向在堆中创建的一个真实对象,这个(数组)对象用以保存指向其他对象的引用。


数组定义与初始化

数组定义

定义一个数组,只需在类型名后加上一对空方括号。

int[] a;  // 更合理,表明类型是 “一个int型数组”

或者,方括号也可以放在标识符后面。

int a[];

现在拥有的只是对数组的一个引用(已经为该引用分配了足够的存储空间),并没有给数组对象本身分配任何空间。
为了给数组创建相应的存储空间,必须写初始化表达式。


数组初始化

1)花括号初始化
有一种特殊的初始化表达式,由一对花括号括起来的值组成,它必须在创建数组的地方出现(定义的同时进行初始化)

int[] a = {1,2,3,4}; 

2)new初始化
如果创建的是基本类型的数组,数组元素中的基本数据类型值会自动初始化成空值(对于数字/字符就是0,对于布尔型就是false

Random rand = new Random(47);   //Random.nextInt()方法会随机返回0到输入参数之间的一个值
int[] a = new int[rand.nextInt(20)];  //定义的同时进行初始化

如果创建的是非基本类型的数组,那就创建了一个引用数组。默认情况下其中所有的引用被自动初始化为null。之后可以通过创建对象,并把对象赋值给引用来完善初始化过程。

Random rand = new Random(47);    //Random.nextInt()方法会随机返回0到输入参数之间的一个值
Integer[] a = new Integer[rand.nextInt(20)];  //整型的包装器类 Integer,它是一个类而不是基本类型
for (int i = 0; i < a.length; i++)
	a[i] = rand.nextInt(500);    //创建新的Integer对象,本例是通过自动包装机制创建的

也可以使用花括号括起来的列表来初始化对象数组。有两种形式:

Integer[] a = {new Integer(1), new Integer(2), 3,};   //初始化列表的最后一个逗号可选
Integer[] a = new Integer[] {new Integer(1), new Integer(2), 3,};  

//Other.main(new String[]{"abc", "de"});    //String对象数组 

可变参数列表

可变参数列表可以应用于参数个数或类型未知的场合。

由于所有的类都直接或间接继承于Object类,所以可以创建以Object数组为参数的方法。

这里,输出建立的类的对象,默认行为(如果没有定义toString()方法的话)打印出的内容是类的名称对象的地址


在Java SE5中,加入可变参数列表的特性,如下示:
有了可变参数,就不用再显式地编写数组语法了。当你指定参数时,编译器实际上会为你去填充数组,所以你获取的仍旧是一个数组。也就是从元素列表到数组的自动转换。如果本身就是个数组,编译器就不会在其上执行任何转换。
在这里插入图片描述

在可变参数列表中也可以使用Object之外类型的参数(也包括int等基本类型),如下面所有的可变参数都必须是String对象。
在这里插入图片描述
在这里插入图片描述 在这里插入图片描述

数组赋值

谨记:数组标识符其实只是个引用,指向在堆中创建的一个真实对象
数组赋值就是对指向数组的引用赋值使之指向另一个数组对象
在这里插入图片描述


多维数组

创建多维数组
可以使用花括号将每个向量分隔开:

int[][] a = {
	{1, 2, 3, }, 
	{4, 5, 6, },
};

也可以使用 new 来分配数组。在不进行显式初始化的情况下,数组的值会被自动初始化

int [][][] a = new int[2][2][4];

粗糙数组
数组中构成矩阵的每个向量都可以具有任意的长度
在这里插入图片描述
在这里插入图片描述
二维数组获取行数a.length
二维数组获取列数a[i].length


Arrays类实用功能

Arrays类是数组的操作类,定义在 java.util 包中,主要功能是实现数组元素的查找、数组内容填充、排序、比较等
在这里插入图片描述

填充数组

Java类库Arrays类提供 Arrays.fill(),用来填充数组。
Arrays.fill()方法作用十分有限,只能用同一个值填充各个位置,而针对对象而言,就是复制同一个引用进行填充。

使用Arrays.fill()可以填充整个数组,或者像示例最后一条语句所示,只填充数组的某个区域
在这里插入图片描述 在这里插入图片描述

复制数组

Java - 数组拷贝的几种方式
Java类库System类提供 System.arraycopy(),用它复制数组比用for循环复制要快很多。

arraycopy() 需要的参数:源数组、从源数组什么位置开始复制的偏移量、目标数组、从目标数组什么位置开始复制的偏移量、需要复制的元素个数
对数组的任何越界操作都会导致异常
在这里插入图片描述 在这里插入图片描述
如果是复制对象数组,那么只是复制了对象的引用——而不是对象本身的拷贝

注:System.arraycopy() 不会执行自动包装和自动拆包,两个数组必须具有相同的确切类型。


数组的比较

Java类库Arrays类提供 Arrays.equals(),用来比较整个数组。

数组相等的条件是元素个数必须相等,并且对应位置的元素也相等。这相当于对每个元素使用equals()作比较来判断(对于基本类型,需要使用基本类型包装器类的equals()方法。如,对于int类型使用 Integer.equals() 作比较)。

在这里插入图片描述 在这里插入图片描述

数组元素的比较

Java有两种方式来提供比较功能。
第一种是实现 java.lang.Comparable 接口,使类具有天生的比较能力。此接口很简单,只有 compareTo() 一个方法。此方法接收另一个Object为参数,如果当前对象小于参数则返回负值,如果相等则返回零,如果当前对象大于参数则返回正值

第二种是创建一个实现了 Comparator 接口的单独的类。这个类有 compare()equals() 两个方法。然而不一定要实现equals()方法,除非有特殊的性能需要,因为无论何时创建一个类,都是间接继承自Object,而Object带有equals()方法。所以只需用默认的Object的equals()方法就可以满足接口的要求了。


数组排序

使用 Arrays.sort() 方法,就可以对任意的基本类型数组排序;
也可以对任意的对象数组进行排序,只要 该对象实现了Comparable接口具有相关联的Comparator
在这里插入图片描述在这里插入图片描述
注意,String排序算法依据词典编排顺序排序,所以大写字母开头的词都放在前面输出,然后才是小写字母开头的词


数组与容器


总结

本章看到了Java对尺寸固定的低级数组提供了适度的支持。这种数组强调的是性能而不是灵活性

在Java的初始版本中,尺寸固定的低级数组绝对是必需的。因为Java早期版本中对容器的支持非常少。因此,选择包含数组总是合理的。
其后的Java版本对容器的支持得到了明显的改进,并且现在的容器在除了性能之外的各个方面都使得数组相形见绌。有了额外的自动包装机制和泛型,在容器中持有基本类型就变得易如反掌了,而这也进一步促使用容器来替换数组。因为泛型可以产生类型安全的容器,因此数组面对这一变化,已经变得毫无优势了。


最初有关效率的论点总是很吸引人,但随着时间的推移,我们看到了与这种思想背道而驰,向着使用像容器这类高级构件的方向的演化。


因此,容器几乎总是更好的选择
当你使用最近的Java版本编程时,应该 “优先选择容器而不是数组”。只有在已证明性能成为问题,并且切换到数组对性能提高有所帮助时,你才应该将程序重构为使用数组。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值