List.of和Arrays.asList有什么区别?

时间:2017-10-05 06:22:33

标签: java list java-9

Java 9为列表引入了新的工厂方法List.of

List<String> strings = List.of("first", "second");

上一个和新选项有什么区别?也就是说,这之间的区别是什么:

Arrays.asList(1, 2, 3);

和此:

List.of(1, 2, 3);

5 个答案:

答案 0 :(得分:125)

Arrays.asList返回可变列表,而List.of返回的列表为immutable

List<Integer> list = Arrays.asList(1, 2, null);
list.set(1, 10); // OK

List<Integer> list = List.of(1, 2, 3);
list.set(1, 10); // Fails with UnsupportedOperationException

Arrays.asList允许null元素而List.of不允许:

List<Integer> list = Arrays.asList(1, 2, null); // OK
List<Integer> list = List.of(1, 2, null); // Fails with NullPointerException

contains与nulls的行为不同:

List<Integer> list = Arrays.asList(1, 2, 3);
list.contains(null); // Returns false

List<Integer> list = List.of(1, 2, 3);
list.contains(null); // Fails with NullPointerException

Arrays.asList返回传递数组的视图,因此对数组的更改也将反映在列表中。对于List.of,这不是真的:

Integer[] array = {1,2,3};
List<Integer> list = Arrays.asList(array);
array[1] = 10;
System.out.println(list); // Prints [1, 10, 3]

Integer[] array = {1,2,3};
List<Integer> list = List.of(array);
array[1] = 10;
System.out.println(list); // Prints [1, 2, 3]

答案 1 :(得分:20)

Arrays.asListList.of

之间的差异

请参阅Stuart Marks的JavaDocs和此talk(或其早期版本)。

我将使用以下代码示例:

List<Integer> listOf = List.of(...);
List<Integer> asList = Arrays.asList(...);
List<Integer> unmodif = Collections.unmodifiableList(asList);

结构不变性(或:不可修改性)

任何结构性更改List.of的尝试都会产生UnsupportedOperationException。其中包括添加设置删除等操作。但是,您可以更改列表中对象的内容(如果对象不是不可变的),因此列表不是“完全不可变的”。

这与使用Collections.unmodifiableList创建的不可修改列表的命运相同。只有此列表是原始列表的视图,因此如果您更改原始列表,它可能会更改。

Arrays.asList不是完全不可变的,它对set没有限制。

listOf.set(1, "a");  // UnsupportedOperationException
unmodif.set(1, "a"); // UnsupportedOperationException
asList.set(1, "a");  // modified unmodif! unmodif is not truly unmodifiable

同样,更改后备阵列(如果你持有它)将改变列表。

结构不变性伴随着许多与防御性编码,并发性和安全性相关的副作用,超出了这个答案的范围。

空敌意

List.of以及Java 1.5以来的任何集合都不允许null作为元素。尝试将null作为元素或甚至查找传递将导致NullPointerException

由于Arrays.asList是1.2(集合框架)中的集合,因此它允许null

listOf.contains(null);  // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null);  // allowed

序列化表格

由于Java 9中引入了List.of,并且此方法创建的列表具有自己的(二进制)序列化形式,因此无法在早期的JDK版本上反序列化(无二进制兼容性 )。但是,您可以使用JSON进行de / serialize,例如。

身份

Arrays.asList内部调用new ArrayList,这可以保证参考不等。

List.of取决于内部实施。返回的实例可以具有引用相等性,但由于无法保证不能依赖它。

asList1 == asList2; // false
listOf1 == listOf2; // true or false

值得一提的是,如果列表包含相同顺序的相同元素,则列表相同(通过List.equals),无论它们是如何创建的,或者是它们支持的操作。

asList.equals(listOf); // true i.f.f. same elements in same order

实施(警告:详细信息可以更改版本)

如果List.of列表中的元素数量为2或更少,则元素存储在专用(内部)类的字段中。一个例子是存储2个元素的列表(部分源代码):

static final class List2<E> extends AbstractImmutableList<E> {
    private final E e0;
    private final E e1;

    List2(E e0, E e1) {
        this.e0 = Objects.requireNonNull(e0);
        this.e1 = Objects.requireNonNull(e1);
    }
}

否则它们以与Arrays.asList类似的方式存储在数组中。

时间和空间效率

基于字段的List.of实现(大小&lt; 2)在某些操作上执行速度稍快。例如,size()可以在不获取数组长度的情况下返回常量,contains(E e)不需要迭代开销。

通过List.of构建不可修改的列表也更快。将上面的构造函数与2个引用赋值(甚至是任意数量的元素的赋值)进行比较

Collections.unmodifiableList(Arrays.asList(...));

创建了2个列表以及其他开销。在空间方面,您保存UnmodifiableList包装器加上一些便士。最终,HashSet等价物的节省更具说服力。

结论时间:如果您想要一个不会更改的列表,请使用List.of;如果您想要一个可以更改的列表,请使用Arrays.asList

答案 2 :(得分:14)

总结 List.of Arrays.asList

之间的差异
  1. List.of可以在数据集较少且未更改时使用,而Arrays.asList可以在大型动态数据集的情况下得到最佳使用。

  2. List.of占用的开销空间非常少,因为它具有基于字段的实现,并且在固定开销和每个元素的基础上消耗更少的堆空间。而Arrays.asList占用更多的开销空间,因为在初始化时它会在堆中创建更多的对象。

  3. List.of返回的集合是不可变的,因此线程安全,而Arrays.asList返回的集合是可变的而不是线程安全的。 (不可变集合实例通常比其可变对应实例消耗更少的内存。)

  4. List.of不允许 null 元素,而Arrays.asList允许 null 元素。

答案 3 :(得分:1)

除上述答案外,List::ofArrays::asList的某些操作也不同:

+----------------------+---------------+----------+----------------+---------------------+
|      Operations      | SINGLETONLIST | LIST::OF | ARRAYS::ASLIST | JAVA.UTIL.ARRAYLIST |
+----------------------+---------------+----------+----------------+---------------------+
|          add         |       ❌       |     ❌    |        ❌       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|        addAll        |       ❌       |     ❌    |        ❌       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|         clear        |       ❌       |     ❌    |        ❌       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|        remove        |       ❌       |     ❌    |        ❌       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|       removeAll      |       ❗️       |     ❌    |        ❗️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|       retainAll      |       ❗️       |     ❌    |        ❗️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|      replaceAll      |       ❌       |     ❌    |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|          set         |       ❌       |     ❌    |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|         sort         |       ✔️       |     ❌    |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|  remove on iterator  |       ❌       |     ❌    |        ❌       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
| set on list-iterator |       ❌       |     ❌    |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
  1. ✔️表示该方法受支持
  2. ❌表示调用此方法将抛出一个 UnsupportedOperationException
  3. ❗️表示仅在方法的参数支持时才支持该方法 不会引起突变,例如 Collections.singletonList(“ foo”)。retainAll(“ foo”)可以,但是 Collections.singletonList(“ foo”)。retainAll(“ bar”)抛出一个 UnsupportedOperationException

有关Collections::singletonList Vs. List::of

的更多信息

答案 4 :(得分:1)

<块引用>

Arrays.asList(1, 2, 3);

将创建固定大小列表

public static void main(String[] args) {
        List<Integer> asList = Arrays.asList(1, 2, 3, 4, 5);
        asList.add(6);    // java.lang.UnsupportedOperationException
        asList.remove(0); // java.lang.UnsupportedOperationException
        asList.set(0, 0); // allowed
}
<块引用>

List.of(1, 2, 3);

一个 Immutable(Java 9)/Unmodifiable(Java 11) List 将被创建:

public static void main(String[] args) {
    List<Integer> listOf = List.of(1, 2, 3, 4, 5);
    listOf.add(6);    // java.lang.UnsupportedOperationException
    listOf.remove(0); // java.lang.UnsupportedOperationException
    listOf.set(0, 0); // java.lang.UnsupportedOperationException
}