java中数组
数组是指一组数据的集合,数组中的每个数据称为元素。在Java中,数组也是Java对象。数组中的元素可以是任意类型(包括基本类型和引用类型),但同一个数组里只能存放类型相同的元素。
数组的定义与初始化
定义及动态初始化
- 方式一,java推荐用法: type [] 变量名 = new type[数组中元素的个数];
//举例
int[] a = new int[10];
for (int i = 0; i < a.length; i++){
a[i] = new Random().nextInt();
}
- 方式二,c语言用法(不推荐): type 变量名 [] = new type[数组中元素的个数];
int a[] = new int[10];
for (int i = 0; i < a.length; i++){
a[i] = new Random().nextInt();
}
静态初始化
int[] a=new int[]{1,2,3};
在定义数组的时候直接初始化,大括号里的值就是数组的值。
隐式初始化
int[] a={1,2,3};
可以不写new,直接使用大括号初始化,但是本质上还是调用了new的,只是可以不写出来而已,所以叫隐式初始化。
最后,我们回过头来仔细的研究一下下面这一句代码,这句代码又做了什么事情?
int[] a = new int[10];
//这句代码做了哪些事呢?
int[] a: 定义了一个int型数组的引用,名字叫做a,存放在栈中。
new int[10]:初始化一个长度为10的int型数组,在堆中开辟相应大小的内存。
int[] a = new int[10]:将堆中开辟的数组的内存地址赋给数组引用a。
数组的使用
数组的引用
可以通过下标来引用数组:arrayName[index];与C、C++不同,Java对数组元素要进行越界检查以保证安全性。这个iOS是一样的。
int[] a=new int[]{2,5,7,4};
System.out.println(a[2]);
//运行结果为 7,[注]数组的下标都是从0开始的,这也是每一种开发语言的共性
数组的长度
java中的每个数组都有一个名为length的属性,表示数组的长度。
int[] a=new int[]{2,5,7,4};
int length = a.length;
System.out.println(length);
//输出结果为:4
数组的遍历
- 方式一:for循环【此方法适应大部分开发语言】
int[] a= new int[]{1,3,5,7,9};
for(int i=0;i<a.length;i++){
System.out.println(a[i] + " ,");
}
//运行结果为: 1 ,3 ,5, 7, 9,
- 方式二:foreach循环
int[] a= new int[]{1,3,5,7,9};
foreach(int element: a){
System.out.println(element);
}
//运行结果为:1 3 5 7 9
数组元素不为基本数据类型
数组是可以存放任意类型的数据的,不一定非得是基本数据类型。数组元素不为基本原生数据类型时,存放的是引用类型,而不是对象本身。当生成对象之后,引用才指向对象,否则引用为null。
Person[] p = new Person[3];
//未生成对象时,引用类型均为空
System.out.println(p[0]);
//生成对象之后,引用指向对象
p[0] = new Person(10);
p[1] = new Person(20);
p[2] = new Person(30);
for(int i = 0; i < p.length; i++){
System.out.println(p[i].age);
}
数组作为方法的参数
public void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
数组作为方法的返回值
public int[] reverse(int[] list) {
int[] result = new int[list.length];
for (int i = 0, j = result.length - 1; i < list.length; i++, j--) {
result[j] = list[i];
}
return result;
}
数组内容的输出
错误示例展示
public static void main(String[] args) {
int a[]={1,9};
System.out.println(a.toString());
}
//[I@61bbe9ba
这输出的是什么奇怪的东西?我们先不管,后面会详细说。那怎么输出数组呢?
- 方式一
public static void main(String [] args){
int a[]={1,9};
for (int i : a){
System.out.println(i);
}
}
- 方式二
public static void main(String [] args){
int a[]={1,9};
System.out.println(Arrays.toString(a));
}
数组内容的比较
数组内容的比较可以使用equals()方法吗? 看代码:
public class ArrayTest{
public static void main(String[] args){
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(a.equals(b));
//结果是false。
}
}
所以证明不能直接用equals()方法比较数组内容,因为没有override Object中的实现,所以仍采用其实现,即采用==实现equals()方法,比较是否为同一个对象。
怎么比较呢?一种解决方案是自己写代码,另一种方法是利用java.util.Arrays。
java.util.Arrays中的方法全是static的。其中包括了equals()方法的各种重载版本。
代码如下:
import java.util.Arrays;
public class ArrayEqualsTest{
public static boolean isEquals(int[] a, int[] b){
if( a == null || b == null ){
return false;
}
if(a.length != b.length){
return false;
}
for(int i = 0; i < a.length; ++i ){
if(a[i] != b[i]){
return false;
}
}
return true;
}
public static void main(String[] args){
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(isEquals(a,b));
System.out.println(Arrays.equals(a,b));
}
}
Arrays类的使用
- 给数组赋值:通过 fill 方法。
- 对数组排序:通过 sort 方法,按升序。
- 比较数组:通过 equals 方法比较数组中元素值是否相等。
- 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
- …….
数组的高级应用
二维数组
二维数组是数组的数组。其实java只有一维数组,但是由于数组可以存放任意类型的数据,当然也就可以存放数组了,这个时候,就可以模拟多维数组了。
基本的定义方式也是两种,代码示例如下:
type[][] i = new type[2][3];//(推荐)
type i[][] = new type[2][3];
变长的二维数组
二维数组的每个元素都是一个一维数组,这些数组不一定都是等长的。
声明二维数组的时候可以只指定第一维大小,空缺出第二维大小,之后再指定不同长度的数组。但是注意,第一维大小不能空缺(不能只指定列数不指定行数)。
public class ArrayTest4{
public static void main(String[] args){
//二维变长数组
int[][] a = new int[3][];
a[0] = new int[2];
a[1] = new int[3];
a[2] = new int[1];
//Error: 不能空缺第一维大小
//int[][] b = new int[][3];
}
}
二维数组也可以在定义的时候初始化,使用花括号的嵌套完成,这时候不指定两个维数的大小,并且根据初始化值的个数不同,可以生成不同长度的数组元素。
int[][] c = new int[][]{{1, 2, 3},{4},{5, 6, 7, 8}};
可变参数
有的时候,你需要一个方法,但是你在调用它之前不知道要传递几个参数给他,这个时候你就需要可变参数了。
public static void main(String [] args){
System.out.println(add(2,3));
System.out.println(add(2,3,5));
}
public static int add(int x,int ...args){
int sum=x;
for(int i=0;i<args.length;i++){
sum+=args[i];
}
return sum;
}
那个奇怪的int ...args
就是可变参数,这样你就可以传递任意个你想传递的数据了。
java把可变参数当做数组处理。
[注意]:可变参数必须位于最后一项。当可变参数个数多余一个时,必将有一个不是最后一项,所以只支持有一个可变参数。因为参数个数不定,所以当其后边还有相同类型参数时,java无法区分传入的参数属于前一个可变参数还是后边的参数,所以只能让可变参数位于最后一项。
数组复制
nt[] a = new int[]{1,2};
int[] b = a;
b [1] = 5;
这个时候a[1]也变成了5,为什么会这样?就不用我多说了吧,所以,要拷贝一个数组,还是需要些技巧的:
- 方式一:System.arraycopy的用法
int[] src = {1,3,5,7,9,11,13,15,17};
int[] dest = {2,4,6,8,10,12,14,16,18,20};
//从src中的第一个元素起复制三个元素,即1,3,5复盖到dest第2个元素开始的三个元素
System.arraycopy(src, 0, dest, 1, 3);
System.out.println(Arrays.toString(dest));
//[2, 1, 3, 5, 10, 12, 14, 16, 18, 20]
- 其他方式:Array类的一些方法:如 Arrays.copyOf,Arrays.copyOfRange等。在下一篇会有专门的介绍。
数组的常见异常
1. NullPointerException 空指针异常
原因: 引用类型变量没有指向任何对象,而访问了对象的属性或者是调用了对象的方法。
2.ArrayIndexOutOfBoundsException 索引值越界。
原因:访问了不存在的索引值。
public static void main(String[] args) {
int[] x = { 1, 2, 3 };
System.out.println(x[3]);
//java.lang.ArrayIndexOutOfBoundsException
}
数组的好处
存数据和不存数据有什么区别吗?数组的最大好处就是能都给存储进来的元素自动进行编号. 注意编号是从0开始。方便操作这些数据。
例如 学生的编号,使用学号就可以找到对应的学生。