Arrays.asList() vs Collections.singletonList() – Arrays.asList() vs Collections.singletonList()

最后修改: 2022年 8月 4日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

List is a commonly used collection type when we work with Java.

List是我们使用Java工作时常用的集合类型。

As we know, we can easily initialize a List in one line. For example, when we want to initialize a List with only one single element, we can use the Arrays.asList() method or the Collections.singletonList() method.

正如我们所知,我们可以很容易地在一行中初始化一个List。例如,当我们想初始化一个只有一个元素的List时,我们可以使用Arrays.asList()方法或Collections.singletonList()方法。

In this tutorial, we’ll discuss the differences between these two methods. Then, for simplicity, we’ll use unit test assertions to verify whether some operations behave as expected.

在本教程中,我们将讨论这两种方法之间的区别。然后,为了简单起见,我们将使用单元测试断言来验证一些操作是否符合预期。

2. The Arrays.asList() Method

2.Arrays.asList()方法

First of all, the Arrays.asList() method returns a fixed-size list.

首先,Arrays.asList()方法返回一个固定大小的列表

Any structural changes will throw UnsupportedOperationException, for example, adding new elements to the list or removing elements from the list. Now, let’s check it with a test:

任何结构上的改变都会抛出不支持操作的异常,例如,向列表中添加新元素或从列表中删除元素。现在,让我们用一个测试来检验一下。

List<String> arraysAsList = Arrays.asList("ONE");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(
    () -> arraysAsList.add("TWO")
);

The test passes if we give it a run. In the code above, we’ve used Assertj’s exception assertion to verify if UnsupportedOperationException is thrown when we try to add a new element to the list.

如果我们让它运行一下,测试就会通过。在上面的代码中,我们使用了Assertj的异常断言来验证当我们试图向列表中添加一个新元素时是否抛出了UnsupportedOperationException

Even though can’t we call add() or remove() operations on the list, we can change the elements in the list using the set() method:

尽管我们不能对列表调用add()remove()操作,我们可以使用set()方法改变列表中的元素

arraysAsList.set(0, "A brand new string");
assertThat(arraysAsList.get(0)).isEqualTo("A brand new string");

This time, we set the element in the list with a new String object. If we execute the test, it passes.

这一次,我们用一个新的String对象来设置列表中的元素。如果我们执行这个测试,它就会通过。

Finally, let’s discuss the relationship between the array of the Arrays.asList() method and the returned list.

最后,我们来讨论一下Arrays.asList()方法的数组和返回的列表之间的关系。

As the method name implies, this method makes an array work as a List. Let’s understand what “making an array work as a List” means.

正如方法名称所暗示的,该方法使一个数组作为List工作。让我们了解一下 “使数组作为List工作 “是什么意思。

The Arrays.asList() method returns a List object, which is backed by the given array. That is to say, the method doesn’t copy the elements from the array to the new List object. Instead, the method provides a List view on the given array. Therefore, any changes we make to the array will be visible in the returned list. Similarly, changes made to the list will be visible in the array too:

Arrays.asList()方法返回一个List对象,它由给定的数组支持。也就是说,该方法并不从数组中复制元素到新的List对象。相反,该方法在给定的数组上提供一个List视图。因此,我们对数组所做的任何改变都将在返回的列表中可见。同样地,对列表所做的改变也会在数组中显示出来:

String[] theArray = new String[] { "ONE", "TWO" };
List<String> theList = Arrays.asList(theArray);
//changing the list, the array is changed too
theList.set(0, "ONE [changed in list]");
assertThat(theArray[0]).isEqualTo("ONE [changed in list]");

//changing the array, the list is changed too
theArray[1] = "TWO [changed in array]";
assertThat(theList.get(1)).isEqualTo("TWO [changed in array]");

The test passes. So for the array and the returned list, if we’ve made some changes on one side, the other side is changed as well.

测试通过。所以对于数组和返回的列表,如果我们在一边做了一些改变,另一边也会被改变。

3. The Collections.singletonList() Method

3.Collections.singletonList()方法

First, the list returned by the singletonList() method has only one element. Unlike the Arrays.asList() method, singletonList() returns an immutable list.

首先,由singletonList()方法返回的列表只有一个元素。与Arrays.asList()方法不同,singletonList()返回一个不可变的列表

In other words, both structural and non-structural changes aren’t allowed to be made on the list returned by singletonList(). A test can quickly illustrate this:

换句话说,结构性和非结构性的改变都不允许在由singletonList()返回的列表上进行。一个测试可以快速说明这一点。

List<String> singletonList = Collections.singletonList("ONE");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(
    () -> singletonList.add("TWO")
);
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(
    () -> singletonList.set(0, "A brand new string")
);

If we run the test, it passes. So, no matter whether we are adding an element to the list or changing the element in the list, it throws UnsupportedOperationException.

如果我们运行这个测试,它就会通过。因此,无论我们是向列表中添加元素还是改变列表中的元素,它都会抛出不支持操作的异常

It’s worth mentioning that if we have a look at the source code of the returned list class, unlike other List implementations, the single element in the returned list isn’t stored in an array or any other complex data structure. Instead, the list holds the element object directly:

值得一提的是,如果我们看一下返回的列表类的源代码,与其他List实现不同,返回的列表中的单个元素并没有存储在一个数组或其他复杂的数据结构中。相反,列表直接持有该元素对象

private static class SingletonList<E> extends AbstractList<E> implements RandomAccess, Serializable {
    ...
    private final E element;

    SingletonList(E obj) {element = obj;}
    ...
}

Therefore, it would take less memory.

因此,它将占用更少的内存。

4. Short Summary

4.简短摘要

Finally, let’s summarize characteristics of the Arrays.asList() method and the Collections.singletonList() method in a table to get a better overview:

最后,让我们在表格中总结一下Arrays.asList()方法和Collections.singletonList()方法的特点,以获得更好的概述。

Arrays.asList() Collections.singletonList()
Structural Changes Not Allowed Not Allowed
 Non-Structural Changes  Allowed Not Allowed
Data Structure Backed by the array Hold the element directly

5. Conclusion

5.总结

In this quick article, we’ve discussed the Arrays.asList() method and the Collections.singletonList() method.

在这篇快速文章中,我们已经讨论了Arrays.asList()方法和Collections.singletonList()方法。

When we want to initialize a fixed-size list with only one single element, we can consider using the Collections.singletonList() method. However, if changing the element in the returned list is required, we can choose the Arrays.asList() method.

当我们想要初始化一个只有一个元素的固定大小的列表时,我们可以考虑使用Collections.singletonList()方法。然而,如果需要改变返回列表中的元素,我们可以选择Arrays.asList()方法。

As always, the full source code of the examples is available over on GitHub.

一如既往,这些示例的完整源代码可在GitHub上获得over