前言

总所周知,在开发过程中我们经常会用到java的数组,集合,这两者者也经常会相互转换,我现在来理一理这其中可能出现的坑以及一些常见的知识。
关于数组的详细说明可以看这篇文章:http://c.biancheng.net/view/906.html

一. 数组

1. 介绍

数组(array)是一种最简单的复合数据类型,它是有序数据的集合,数组中的每个元素具有相同的数据类型,可以用一个统一的数组名和不同的下标来确定数组中唯一的元素。根据数组的维度,可以将其分为一维数组、二维数组和多维数组等。

在计算机语言中数组是非常重要的集合类型,大部分计算机语言中数组具有如下三个基本特性:

  1. 一致性:数组只能保存相同数据类型元素,元素的数据类型可以是任何相同的数据类型。
  2. 有序性:数组中的元素是有序的,通过下标访问。
  3. 不可变性:数组一旦初始化,则长度(数组中元素的个数)不可变。

总的来说,数组具有以下特点:

  • 数组可以是一维数组、二维数组或多维数组。
  • 数值数组元素的默认值为 0,而引用元素的默认值为 null。
  • 数组的索引从 0 开始,如果数组有 n 个元素,那么数组的索引是从 0 到(n-1)。
  • 数组元素可以是任何类型,包括数组类型。
  • 数组类型是从抽象基类 Array 派生的引用类型。

    2. 一维数组

    这里仅介绍我们常用的一维数组,其他不常用的数组类型可以点击开头的链接了解

    2.1 声明数组

    为了在程序中使用一个数组,必须声明一个引用该数组的变量,并指明整个变量可以引用的数组类型。声明一维数组的语法格式为:
    1. //第一种
    2. type[] arrayName; // 数据类型[] 数组名
    3. //第二种
    4. type arrayName[]; // 数据类型 数组名[]
    声明数组有两种格式,我们通常采用第一种格式来声明数组,例如 String[] a; ,需要注意的是,数组在声明时不需要规定大小
    1. int score[10]; // 这是错误的

2.2 分配空间

声明了数组,只是得到了一个存放数组的变量,并没有为数组元素分配内存空间,不能使用。因此要为数组分配内存空间,这样数组的每一个元素才有一个空间进行存储。
简单地说,分配空间就是要告诉计算机在内存中为它分配几个连续的位置来存储数据。在 Java 中可以使用 new 关键字来给数组分配空间,语法如下

  1. //第一种方法,仅分配空间
  2. int[] arr;
  3. arr = new int[6];
  4. //第二种方法,分配的同时给数组赋值
  5. int[] y;
  6. y = new int[]{1,2,3,4,5};

2.3 创建数组

java中有三种创建数组的方式,除了上面提到的两种方法,还可以直接省略new来创建数组;

  1. //第三种方法
  2. int[] y = {1,2,3,4,5};

采用这种方法来创建数组,不能将数组的声明和赋值分开,必须同步进行,下面就是一个错误的例子

  1. //我是错误的
  2. int[] y;
  3. y = {1,2,3,4,5};

然后就是数组的取值和遍历想必大家都清楚,不作过多阐述

2.3 Java Arrays工具类

Arrays 类是一个工具类,其中包含了数组操作的很多方法。这个 Arrays 类里均为 static 修饰的方法(static 修饰的方法可以直接通过类名调用),可以直接通过 Arrays.xxx(xxx) 的形式调用方法,现在我介绍一下我们经常会使用到的方法:

1)copyOf(type[] original, int length)

这个方法将会把 original 数组复制成一个新数组,其中 length 是新数组的长度。如果 length 小于 original 数组的长度,则截取原数组的前面 length 个元素,如果 length 大于 original 数组的长度,则后面补充 0(数值类型)、false(布尔类型)或者 null(引用类型)。

2)copyOfRange(type[] original, int from, int to)

这个方法与前面方法相似,但这个方法只复制 original 数组的 from 索引到 to 索引的元素。

3)equals(type[] a, type[] a2)

如果 a 数组和 a2 数组的长度相等,而且 a 数组和 a2 数组的数组元素也一一相同,该方法将返回 true。
需要注意的是,这里的相同是通过”==”号来比较的,对引用类型的数组要慎用

4)fill(type[] a, type val)

该方法将会把 a 数组的所有元素都赋值为 val。

5)fill(type[] a, int fromIndex, int toIndex, type val)

该方法与前一个方法的作用相同,区别只是该方法仅仅将 a 数组的 fromIndex 到 toIndex 索引的数组元素赋值为 val。

6)toString(type[] a)

该方法将一个数组转换成一个字符串。该方法按顺序把多个数组元素连缀在一起,多个数组元素使用英文逗号,和空格隔开。

2.3 数组字符串互转

1)char数组转字符串

利用String的原生方法实现

  1. //构造方法(推荐)
  2. char[] arr={'a','b','c'};
  3. String str1 =new String(arr);//abc
  4. System.out.println(str1); // 012345
  5. //valueof 或 copyvalueof方法,两者底层其实都是调用了构造方法
  6. String str2 = String.valueOf(arr);
  7. String str3 = String.copyvalueOf(arr);
  8. System.out.println(str2); // 012345

2) String数组->字符串

方法一:利用StringBuilder遍历拼接

  1. String[] arr = { "0", "1", "2", "3", "4", "5" };
  2. StringBuilder builder = new StringBuilder();
  3. for (String s : arr) {
  4. builder.append(s);
  5. }
  6. System.out.println(builder.toString()); // 012345

方法二:使用long3包下的StringUtils的join方法(推荐)

  1. //不带分隔符
  2. String[] arr = { "0", "1", "2", "3", "4", "5" };
  3. String str1 = StringUtils.join(arr); // 数组转字符串,底层用StringBuilder实现
  4. System.out.println(str1); // 012345
  5. //带分隔符
  6. String str2 = StringUtils.join(arr, ","); // 数组转字符串(逗号分隔)(推荐)
  7. System.out.println(str2); // 0,1,2,3,4,5

方法三: 使用lang3下的ArrayUtils的toString方法

  1. String[] arr = { "0", "1", "2", "3", "4", "5" };
  2. String str = ArrayUtils.toString(arr, ","); // 数组转字符串(逗号分隔,首尾加大括号)
  3. System.out.println(str); // {0,1,2,3,4,5}

2.4 数组集合互转

1) 数组转List

方法一:直接利用Arrays工具类的asList方法(不推荐)

  1. String[] pod = new String[]{"haha", "xixi", "heihei"};
  2. List<String> list = Arrays.asList(pod);
  3. for (String bean : list) {
  4. System.out.println(bean);
  5. }

asList会返回一个装载了数组a中所有数据的固定长度的List,源码如图所示
image.png
需要注意的是这里返回的ArrayList并不是我们通常使用的ArrayList,而是Arrays工具类的内部类,利用适配器模式来将数组展现成List的样子,实际上还是数组,源码如图
image.png

方法二:利用Arrays工具类的asList方法和ArrayList本身的构造方法结合

  1. String[] pod = new String[]{"haha", "xixi", "heihei"};
  2. List<String> list = Arrays.asList(pod);
  3. List<String> newList = new ArrayList<String>(list);
  4. for (String bean : newList) {
  5. System.out.println(bean);
  6. }

这样创建的类就没有问题了,如图
image.png

2)List转数组

方法一:我们常用的集合类都继承了AbstractCollection抽象方法,实现了toArray接口,调用toArray ( T[ ] a )方法即可实现List to Array。需要注意的是,如果传入的数组 T[ ] a太小放不下list的所有元素,会放入一个新的数组中。

  1. List<Integer> pod = new ArrayList<Integer>();
  2. for(int i = 0; i < 5; i++){
  3. pod.add(i);
  4. }
  5. Integer[] array=pod.toArray(new Integer[pod.size()]);
  6. System.out.println(array);

AbstractCollection还有一个无参的方法toArray(),如果使用这个方法返回Object[],无法强转成指定的数组

  1. //这是一个错误的实例
  2. List<Integer> pod = new ArrayList<Integer>();
  3. for(int i = 0; i < 5; i++){
  4. pod.add(i);
  5. }
  6. Integer[] array= (Integer[]) pod.toArray();