1 List 概览

image.png

2 List 初始化

参考博客

2.1 使用 List.add() 方法

  1. List<String> strList = new LiknedList<>();
  2. strList.add("a");
  3. strList.add("b");
  4. strList.add("c");

2.2 使用 {{}} 双括号语法

  1. List<String> strList = new LinkedList<>() {{
  2. add("a");
  3. add("b");
  4. add("c");
  5. }}

这种方式相对方便了一些。

外层的 {} 定义了一个 LinkedList 的匿名内部类。内层的 {} 的定义了一个实例初始化代码块。 这个代码块在初始化内部类时执行。所以这里相当于定义了一个匿名内部类,并使用 add 添加元素来初始化。

这种方式有几个缺点

  • 使用匿名内部类,会有效率上的损失。当然在大多数情况下,这点效率都是可接受的。
  • 静态内部类持有所在外部类的引用。如果需要将 List 返回给到其他地方使用,可能造成内存泄漏。

2.3 使用 Arrays.asList()

  1. List<String> strList = Arrays.asList("a", "b", "c");

这种方式使用了 java.util.Arrays 的静态方法。写法上比之前的两种都更简洁,也没有构造匿名内部类的效率问题。

但也有几点需要注意:

  • Arrays.asList 返回的是 **Arrays** 的静态内部类(静态内部类不持有所在外部类的引用)。

这个内部类继承自 AbstractList,实现了 RandomAccess,内部使用了一个数组来存储元素。但是不支持增删元素。这点需要注意。如果只是使用 Arrays.asList 来初始化常量,那么这点就不算什么问题了。

  • Arrays.asList 的参数如果是基本类型的数组时,需要留意返回值可能和你预期的不同。 ```java int[] intArray = new int[]{1, 2, 3}; Integer[] integerArray = new Integer[]{1, 2, 3};

List intArrayList = Arrays.asList(intArray); List integerList = Arrays.asList(integerArray); List integerList2 = Arrays.asList(1, 2, 3);

  1. 这里 `Arrays.asList(intArray)` 的返回值是 `List<int[]>` 而不是 `List<Integer>`。这一点也算不上问题,只是使用时需要留意。如果能在 Java 中做到尽量使用 List Integer,尽量避免使用 int 等基本类型和 `[]` 这种较为底层的数据结构即可避免。
  2. 虽然本文是在讲初始化 `List`,**但这里的 ****`{{}}`**** 双括号语法同样可用于初始化 ****`Map`**** 等其他众多类型**。相对而言,`Arrays.asList` 就只能用于初始化 `List` 类型了。
  3. <a name="ZUkUv"></a>
  4. ## 2.4 使用 `Stream` (JDK8)
  5. ```java
  6. List<String> list = Stream.of("a", "b", "c").collect(Collectors.toList());

单纯初始化 List,使用 Stream 有点大材小用了。

2.5 使用 Lists (JDK9)

  1. List<String> list = Lists.newArrayList("a", "b", "c");

3 List 与数组相互转换

3.1 List 转数组

  1. 使用 for 循环

    1. // 'List' needs to convert.
    2. List<String> list = new ArrayList<>() {{ add("aa"); add("bb"); add("cc"); add("dd"); }};
    3. String array = new String[list.size()];
    4. for (int i = 0; i < list.size(); ++i) {
    5. array[i] = list.get(i);
    6. }

    当然这种方法是最朴素的,一般我们也不会用

  1. List 的 toArray() 方法

特别注意,不能这样写:

  1. ArrayList<String> list = new ArrayList<String>();
  2. String strings[] = (String [])list.toArray();

这样写编译没什么问题,但运行时会报 ClassCastException,这是因为 Java 种允许向上和向下转型,但是这个转型是否成功是根据 JVM 种这个对象的类型来实现的。JVM 中保存了每个对象的类型,而数组也是一个对象,其类型是 java.lang.Object。将 java.lang.Object 转换为 java.lang.String 是显然不可能的事情,因为这是一个向下转型(学过对象与多态的一定知道为什么)。

所以正确的方法是这样的:

  1. List<String> list = new ArrayList<>() {{ add("aa"); add("bb"); add("cc"); add("dd"); }}
  2. String[] array = list.toArray(new String[list.size()]);

3.2 数组转 List

  1. 使用 for 循环

    1. String[] array = new String[] {"aa", "bb", "cc"};
    2. List<String> list = new ArrayList<>();
    3. for (String str : array) {
    4. list.add(str);
    5. }
  2. ArraysasList() 方法(推荐使用

    1. List<String> arrayList = new ArrayList<>(Arrays.asList(array));
  3. ArraysasList() 方法(不推荐,扩展知识用)

    1. List<String> arrayList = Arrays.asList(array);

    同方法二一样使用了 asList() 方法。这不是最好的,因为 asList() 返回的列表的大小是固定的。事实上,返回的列表不是 java.util.ArrayList,而是定义在 java.util.Arrays 中一个私有静态类。我们知道 ArrayList 的实现本质上是一个数组,而 asList() 返回的列表是由原始数组支持的固定大小的列表。这种情况下,如果添加或删除列表中的元素,程序会抛出异常 UnsupportedOperationException

  1. 使用 Collections.addAll()
    1. List<String> list = new ArrayList<>(array.length());
    2. Collections.addAll(list, array);

参考链接
https://blog.csdn.net/zjx2016/article/details/78273192