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

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

以前的选择和新的选择有什么不同?也就是说,这两者之间的区别是什么

Arrays.asList(1, 2, 3);

这:

List.of(1, 2, 3);

数组。asList返回一个可变列表,而list返回list。Of是不可变的:

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

数组。当List时,asList允许空元素。不:

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

Contains对null的行为不同:

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

数组。asList返回传递数组的视图,因此对数组的更改也将反映在列表中。为列表。这是不正确的:

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]

让我们总结一下List之间的区别。和Arrays.asList

List.of can be best used when data set is less and unchanged, while Arrays.asList can be used best in case of large and dynamic data set. List.of take very less overhead space because it has field-based implementation and consume less heap space, both in terms of fixed overhead and on a per-element basis. while Arrays.asList take more overhead space because while initialization it creates more objects in heap. Collection returned by List.of is immutable and hence thread-safe while Collection returned by Arrays.asList is mutable and not thread safe. (Immutable collection instances generally consume much less memory than their mutable counterparts.) List.of doesn't allow null elements while Arrays.asList allows null elements.


数组之间的区别。asList和List.of

请参阅JavaDocs和Stuart Marks的演讲(或以前的版本)。

我将使用以下代码示例:

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

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

任何改变List结构的尝试。的操作将导致UnsupportedOperationException。这包括添加、设置和删除等操作。但是,您可以更改列表中对象的内容(如果对象不是不可变的),因此列表不是“完全不可变的”。

对于使用Collections.unmodifiableList创建的不可修改列表来说,情况也是如此。只有这个列表是原始列表的视图,所以如果您更改原始列表,它也可以更改。

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

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

类似地,更改支持数组(如果您持有它)将更改列表。

结构不变性带来了许多与防御性编码、并发性和安全性相关的副作用,这些都超出了本文的范围。

空的敌意

列表。的和Java 1.5以后的任何集合都不允许null作为元素。试图将null作为一个元素传递,甚至是一个查找都会导致NullPointerException。

因为数组。asList是1.2(集合框架)中的一个集合,它允许为空。

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

序列化形式

从列表中。of已经在Java 9中引入,通过这种方法创建的列表有自己的(二进制)序列化形式,它们不能在早期的JDK版本上反序列化(不兼容二进制)。但是,例如,您可以使用JSON反/序列化。

身份

数组。asList内部调用new ArrayList,这保证了引用不平等。

列表。的值取决于内部实现。返回的实例可以具有引用相等性,但由于不能保证这一点,所以不能依赖它。

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

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

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

实现(警告:详细信息可能随版本而改变)

如果list中的元素个数。的值为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的方式存储在数组中。

时空效率

列表中。基于字段的实现(大小<2)在某些操作上执行得稍微快一些。例如,size()可以返回一个常量而不获取数组长度,contains(E E)不需要迭代开销。

通过list构造一个不可修改的列表。的速度也更快。将上面的构造函数与两个引用赋值(甚至任意数量的元素)进行比较

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

这会创建2个列表加上其他开销。就空间而言,您节省了UnmodifiableList包装器和一些便士。最终,HashSet等价的节省更令人信服。


总结时间:使用List。当你想要一个不改变的列表和数组。当您想要一个可以更改的列表时(如上所示)。


除了上面的答案,还有一些操作List::of和Arrays::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 |       ❌      |     ❌  |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+

✔️表示支持该方法 ❌表示调用此方法将抛出 UnsupportedOperationException ❗️表示只有在方法的参数支持时才支持该方法 不会引起突变,例如 Collections.singletonList("foo").retainAll("foo")是可以的,但是 Collections.singletonList .retainAll(“foo”)(“酒吧”)抛出 UnsupportedOperationException

更多关于Collections::singletonList Vs. List::of


Arrays.asList(1, 2, 3);

将创建一个固定大小的List:

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);

一个不可变(Java 9)/不可修改(Java 11)列表将被创建:

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
}