[09] 数组


1、基本概述

数组属于对象,它是相同数据类型元素的集合,这里的数据类型,既可以存储基本数据类型,也可以存储引用数据类型。

对于数组的声明,有两种方式
  • 数据类型 [ ] 数组变量名 (如 int [ ] arr
  • 数组类型 数组变量名 [ ] (如 int arr [ ]

虽然两者并没有本质上的区别,但从可读性上建议使用 int[ ] arr 的方式。

数组的创建方式有三种
  • 声明数组的同时,只指定其长度,数组中的值都为默认的初始化值(动态创建,可以结合for循环进行赋值)
  • e.g. char[ ] arr = new char[10];

  • 声明数组的同时,初始化其内部的值(静态创建)
  • e.g. int[ ] arr = new int[ ]{1, 2, 3, 4, 5};  

  • 和第二种方式相同,但语法更简单(同上)
  • e.g. int[ ] arr = {1, 2, 3, 4, 5};

注意:
  • 数组初始化时必须直接或间接定义长度,且其长度一经定义不允改变
  • 未定义元素值得数组,其元素初始化值跟数据类型有关,如int为0,char为'',String则为null
  • 数组的长度是属性length,而String的长度是方法length()
  • 数组是对象,所以直接赋值给另一个数组,实际上只是改变了引用,而不是复制



2、数组的访问和迭代

2.1 数组的访问

数组中单个元素的访问,使用 数组名 [索引] 的方式,比如 arr[2]; 将访问数组中第三个元素。

注意:
  • 数组的索引从0开始
  • 索引的数据类型是整型
  • 索引最大值和数组长度始终差1

2.2 数组的迭代

2.2.1 for循环

int[] arr = new int[]{1, 2, 3, 4, 5, 6};  
System.out.println(arr[0]);
System.out.println(arr[2]);
//数组的迭代
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

2.2.2 for each 增强for循环

int[] arr = new int[]{1, 2, 3, 4, 5, 6};
System.out.println(arr[0]);
System.out.println(arr[2]);
//数组的迭代
for (int ele : arr) {
    System.out.println(ele);
}
for (数组元素的类型  临时变量名 : 数组的名字){ ... }



3、二维数组

二维数组,即数组中存储的元素也为数组,形如:int[][] arr = {{1}, {1, 2}, {1, 2, 3}};

二维数组的声明方式示例如下,仍然建议使用第一种:
  • int [ ] [ ] arr
  • int [ ] arr [ ]
  • int arr [ ] [ ]

二维数组的创建方式示例如下:
  • int [ ] [ ] arr = new int [ n ] [ m ];n不可省略,即最外层数组长度必须定义,m表子数组长度,可以省略不定义)
  • int [ ] [ ] arr = {{1,2,3,4}, {1,2,3,4}, {1,2,3,4}};



4、数组的拷贝

我们说过,想要拷贝数组,是不能直接通过赋值的,因为对象的缘故,只是改变了其引用,本质上并不是复制。

你可以使用循环赋值的方式来获得一个新的数组,但是这种方式未免太笨拙了一些。在JDK API的System类中,已经为我们提供了一个数组拷贝的静态方法:arraycopy
//从指定源数组,复制从指定位置开始,到指定数组的指定位置结束,复制指定长度个元素
arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

拷贝示例:
int[] arr1 = {10, 100, 1000};
int[] arr2 = {20, 200, 2000, 20000};

//从arr1[1]开始,赋值到arr2,从arr[2]开始,共复制2个元素
System.arraycopy(arr1, 1, arr2, 2, 2);

for (int bean : arr1) {
    System.out.print(bean + ", ");
}
System.out.println();
for (int bean : arr2) {
    System.out.print(bean + ", ");
}

//结果:
//10, 100, 1000, 
//20, 200, 100, 1000, 

实际上,你还可以使用从Object上继承下来的clone方法,不过该方法是浅克隆:
  • 浅克隆:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象
  • 深克隆:被复制对象的所有变量都含有与原来的对象相同的值,而那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些

所以,为了避免出错,在某个数组的元素类型是基本数据类型时,完全可以使用clone方法,如果元素类型为其他对象,则使用时要慎重



5、数组的常用操作

数组虽然属于对象,但是几乎没有自身的方法,基本上都是从Object类上继承下来的。需要数组的操作,要通过一个工具类中大量的静态方法来实现,Arrays类(注意有s)

5.1 数组转换为集合

Arrays有asList方法可以直接将数组转换为List:
String[] arr = {"zhangsan", "lisi", "wangwu"};
List<String> temp = Arrays.asList(arr);

for (String bean : temp) {
    System.out.println(bean);
}

//输出
//zhangsan
//lisi
//wangwu

如果要转换为Set,要利用其构造函数允许传入参数为Collection的子类,但注意乱序的同时会覆盖重复的元素:
String[] arr = {"zhangsan", "lisi", "wangwu", "wangwu"};
Set<String> temp = new HashSet<String>(Arrays.asList(arr));

for (String bean : temp) {
    System.out.println(bean);
}

//输出
//wangwu
//lisi
//zhangsan

如果数组的元素类型为基本数据类型,因为不是对象,而集合的对象必须为对象(这里方法中没有使用自动装箱),所以只能用笨办法:
int[] arr = {1, 3, 5, 2, 4, 6};
List<Integer> list = new ArrayList<Integer>();
for (int ele : arr) {
    list.add(ele);
}

for (Integer bean : list) {
    System.out.println(bean);
}

5.2 判断数组是否包含某个元素

曲线救国的方式,先将数组转为List,通过List的contains来判断:
String[] arr = {"zhangsan", "lisi", "wangwu"};
boolean result = Arrays.asList(arr).contains("lisi");
System.out.println(result);

//结果
//true

当然,也可以先转换为字符串,使用字符串的contains方法;亦或者自循环进行判断。



6、参考链接



posted @ 2017-09-01 10:05  Dulk  阅读(282)  评论(0编辑  收藏  举报