我想创建一个用于测试的选项列表。起初,我这样做:

ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

然后,我将代码重构如下:

ArrayList<String> places = new ArrayList<String>(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

有更好的方法吗?


当前回答

如果您只是将其声明为List,这会更简单——它必须是ArrayList吗?

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

或者如果您只有一个元素:

List<String> places = Collections.singletonList("Buenos Aires");

这意味着位置是不可变的(尝试更改它将导致引发UnsupportedOperationException异常)。

要创建一个可变列表,即一个具体的ArrayList,您可以从不可变列表中创建一个ArrayList:

ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

并导入正确的软件包:

import java.util.Arrays;

其他回答

简单的答案

Java 9或更高版本:

List<String> strings = List.of("foo", "bar", "baz");

这将为您提供一个不可变的列表,因此无法更改。在大多数情况下,这就是你想要的。

Java 8或更早版本:

List<String> strings = Arrays.asList("foo", "bar", "baz");

这将为您提供一个由数组支持的List*,因此它不能更改长度。但是您可以调用List.set(…),所以它仍然是可变的。

*实现细节:它是java.util.Arrays内部的一个私有嵌套类,名为ArrayList,这是一个与java.util.ArrayList不同的类,尽管它们的简单名称相同。

静态导入

您可以通过静态导入使Java 8 Arrays.asList更短:

import static java.util.Arrays.asList;  
...
List<String> strings = asList("foo", "bar", "baz");

任何现代IDE*都会为您建议并执行此操作。

我不建议静态地导入List.of方法,因为它会令人困惑。

*例如,在IntelliJ IDEA中,按Alt+Enter并选择静态导入方法。。。

使用流

为什么必须是列表?对于Java 8或更高版本,您可以使用更灵活的Stream:

Stream<String> strings = Stream.of("foo", "bar", "baz");

您可以连接流:

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

或者您可以从“流”转到“列表”:

import static java.util.stream.Collectors.toList;
...
var strings = Stream.of("foo", "bar", "baz").toList(); // Java 16

List<String> strings = Stream.of("foo", "bar", "baz").collect(toList()); // Java 8

但最好只使用流而不将其收集到列表中。

如果您特别需要java.util.ArrayList*

如果要预先填充ArrayList并在之后添加到其中,请使用

List<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");

或Java 8或更早版本:

List<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");

或使用流:

import static java.util.stream.Collectors.toCollection;

List<String> strings = Stream.of("foo", "bar")
                             .collect(toCollection(ArrayList::new));
strings.add("baz");

但同样,最好直接使用流,而不是将其收集到列表中。

*您可能不需要特别的ArrayList。引用JEP 269:

使用预定义的值集初始化可变集合实例有一小组用例。通常最好将这些预定义的值放在不可变集合中,然后通过复制构造函数初始化可变集合。

(强调矿井)

程序到接口,而不是实现

您说过您已经在代码中将列表声明为ArrayList,但只有当您使用的ArrayList的某个成员不在list中时,才应该这样做。

这是你最可能不做的。

通常,您应该只通过要使用的最通用的接口(例如Iterable、Collection或List)声明变量,并使用特定的实现(例如ArrayList、LinkedList或Arrays.asList())初始化它们。

否则,您将代码限制为特定类型,并且在需要更改时将更难更改。

例如,如果要将ArrayList传递给void方法(…):

// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) { 
    for (String s : strings) { ... } 
}

// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
    if (!strings.isEmpty()) { strings.stream()... }
}

// List if you also need random access, .get(index):
void method(List<String> strings) {
    strings.get(...)
}

// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
    ??? // You don't want to limit yourself to just ArrayList
}

另一个例子是总是将变量声明为InputStream,即使它通常是FileInputStream或BufferedInputStream,因为很快有一天你或其他人会想要使用其他类型的InputStream。

您可以使用以下语句:

代码段:

String [] arr = {"Sharlock", "Homes", "Watson"};

List<String> names = Arrays.asList(arr);

在Java 9中,我们可以很容易地在一行中初始化ArrayList:

List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");

or

List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

Java 9的这种新方法与以前的方法相比有许多优点:

空间效率不可变性线程安全

有关更多详细信息,请参阅本文->List.of和Arrays.asList之间的区别是什么?

这是算盘常见的代码

// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// Or for Immutable List/Set/Map
ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// The most efficient way, which is similar with Arrays.asList(...) in JDK. 
// but returns a flexible-size list backed by the specified array.
List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");

声明:我是算盘通用的开发者。

使用Array.asList(“布宜诺斯艾利斯”、“科尔多瓦”、“拉普拉塔”);是正确的。但任何对Arrays.asList()的调用如果没有参数或只有一个参数,都可以用对Collections.singletonList()或Collections.emptyList()进行替换,这样可以节省一些内存。

注意:Collections.singletonList()返回的列表是不可变的,而列表返回的Arrays.asList()允许调用set()方法。在极少数情况下,这可能会破坏代码。