Java 使用一行代码初始化列表 List
1. 概述
在这个快速教程中,我们将研究如何使用单行代码初始化列表。
2. 从数组创建
我们可以从数组创建一个列表。多亏了数组文字,我们可以在一行中初始化它们:
List<String> list = Arrays.asList(new String[]{"foo", "bar"});
我们可以信任 varargs 机制来处理数组创建。这样,我们就可以编写更简洁易读的代码:
@Test
public void givenArraysAsList_thenInitialiseList() {
List<String> list = Arrays.asList("foo", "bar");
assertTrue(list.contains("foo"));
}
此代码的结果实例实现了 List 接口,但它不是 java.util.ArrayList 或 LinkedList。 相反,它是一个由原始数组支持的列表,它有两个含义,我们将在本节的其余部分中讨论。
尽管该类的名称恰好是 ArrayList,但它位于 java.util.Arrays 包中。
2.1.固定大小
Arrays.asList 的结果实例将具有固定大小:
@Test(expected = UnsupportedOperationException.class)
public void givenArraysAsList_whenAdd_thenUnsupportedException() {
List<String> list = Arrays.asList("foo", "bar");
list.add("baz");
}
2.2.共享引用
原始数组和列表共享对对象的相同引用:
@Test
public void givenArraysAsList_whenCreated_thenShareReference(){
String[] array = {"foo", "bar"};
List<String> list = Arrays.asList(array);
array[0] = "baz";
assertEquals("baz", list.get(0));
}
3. 从流创建 (Java 8)
我们可以轻松地将流转换为任何类型的集合。
因此,通过 Streams 的工厂方法,我们可以在一行中创建和初始化列表:
@Test
public void givenStream_thenInitializeList(){
List<String> list = Stream.of("foo", "bar")
.collect(Collectors.toList());
assertTrue(list.contains("foo"));
}
这里我们应该注意,Collectors.toList() 并不能保证返回的 List 的准确实现。
关于返回实例的可变性、可序列化性或线程安全性没有一般约定。因此,我们的代码不应依赖于任何这些属性。
一些消息来源强调,Stream.of(...).collect(...) 可能比 Arrays.asList() 具有更大的内存和性能占用量。但在几乎所有情况下,这种微观优化几乎没有什么区别。
4.工厂方法(Java 9)
JDK 9 引入了几种方便的集合工厂方法:
List<String> list = List.of("foo", "bar", "baz");
Set<String> set = Set.of("foo", "bar", "baz");
一个重要的细节是返回的实例是不可变的。除此之外,工厂方法在空间效率和线程安全性方面还有一些优势。
本文对此主题进行了更多探讨。
5. 双括号初始化
在几个地方,我们可以找到一种称为双括号初始化的方法,如下所示:
@Test
public void givenAnonymousInnerClass_thenInitialiseList() {
List<String> cities = new ArrayList() {{
add("New York");
add("Rio");
add("Tokyo");
}};
assertTrue(cities.contains("New York"));
}
“双括号初始化”这个名字很有误导性。虽然语法看起来紧凑而优雅,但它危险地隐藏了幕后发生的事情。
Java 中实际上没有双括号语法元素;这是两个故意以这种方式格式化的块。
使用外部大括号,我们声明一个匿名内部类,它将成为 ArrayList 的子类。我们可以在这些大括号内声明子类的详细信息。
像往常一样,我们可以使用实例初始化块,这就是内部大括号对的来源。
这种语法的简洁性很有吸引力。然而,它被认为是一种反模式。
要了解有关双括号初始化的更多信息,请查看我们的文章此处。
六,结论
现代 Java 提供了多种选项来在一行中创建集合。我们选择的方法几乎完全取决于个人喜好,而不是技术推理。
一个重要的结论是,尽管它看起来很优雅,匿名内部类初始化的反模式(又名双大括号)有许多负面影响。
与往常一样,代码可以在 GitHub 上获取。