我想创建一个用于测试目的的选项列表。起初,我这样做了:
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"));
有一个更好的方法吗?
实际上,可能是初始化的“最佳”方式 ArrayList
是你写的方法,因为它不需要创建一个新的 List
以任何方式:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
问题是需要进行相当多的输入才能引用它 list
实例。
还有其他选择,例如使用实例初始化程序创建匿名内部类(也称为“双括号初始化”):
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
但是,我不太喜欢那种方法,因为你最终得到的是它的子类 ArrayList
它有一个实例初始化器,并且创建该类只是为了创建一个对象 - 这对我来说似乎有点过分。
如果是的话,本来会很棒的 Collection Literals提案 对于 项目硬币 被接受(它被定义为在Java 7中引入,但它也不可能成为Java 8的一部分。):
List<String> list = ["A", "B", "C"];
不幸的是,它不会帮助你,因为它将初始化一个不可变的 List
而不是一个 ArrayList
而且,它还没有,如果有的话。
如果你只是声明它是一个更简单 List
- 它必须是一个ArrayList吗?
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
或者,如果您只有一个元素:
List<String> places = Collections.singletonList("Buenos Aires");
这意味着 places
是 一成不变 (试图改变它会导致一个 UnsupportedOperationException
要抛出的异常)。
制作一个具体的可变列表 ArrayList
你可以创建一个 ArrayList
从不可变列表:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
简单的答案
在Java 8或更早版本中:
List<String> strings = Arrays.asList("foo", "bar", "baz");
这会给你一个 List
由数组支持,所以它不能改变长度。
但你可以打电话 List.set
,所以它仍然是可变的。
在Java 9中:
List<String> strings = List.of("foo", "bar", "baz");
这将给你一个不可改变的 List
,所以它无法改变。
在您预先填充它的大多数情况下,这是您想要的。
答案越短
你(们)能做到 Arrays.asList
静态导入甚至更短:
List<String> strings = asList("foo", "bar", "baz");
静态导入:
import static java.util.Arrays.asList;
任何现代IDE都会建议并自动为您做。
例如,在IntelliJ IDEA中按下 Alt+Enter
并选择 Static import method...
。
但是,我不建议缩短Java 9 List.of
方法,因为刚刚 of
变得混乱。
List.of
已经很短了,读起来也不错。
运用 Stream
小号
为什么它必须是一个 List
?
使用Java 8或更高版本,您可以使用 Stream
哪个更灵活:
Stream<String> strings = Stream.of("foo", "bar", "baz");
你可以连接 Stream
S:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
或者你可以去一个 Stream
到了 List
:
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
但最好是,只需使用 Stream
没有把它收集到一个 List
。
如果你 真 特别需要一个 java.util.ArrayList
(你可能没有。)
去引用 JEP 269 (强调我的):
有一个 小集 用于使用预定义的值集初始化可变集合实例的用例。通常最好将这些预定义值放在不可变集合中,然后通过复制构造函数初始化可变集合。
如果你想 都 预填充 ArrayList
和 之后添加(为什么?),使用
List<String> strings = new ArrayList<>(asList("foo", "bar", "baz"));
或者在Java 9中:
List<String> strings = new ArrayList<>(List.of("foo", "bar", "baz"));
或使用 Stream
:
List<String> strings = Stream.of("foo", "bar", "baz")
.collect(toCollection(ArrayList::new));
但同样,最好只使用 Stream
直接而不是收集它 List
。
编程到接口,而不是实现
你说你已经将列表声明为 ArrayList
在你的代码中,但是你应该只在你使用某些成员时才这样做 ArrayList
那不是 List
。
你很可能不会这样做。
通常你应该通过你将要使用的最通用的接口声明变量(例如 Iterable
, Collection
, 要么 List
),并用具体实现初始化它们(例如, ArrayList
, LinkedList
要么 Arrays.asList()
)。
否则,您将代码限制为特定类型,并且在您需要时更难更改。
例如:
// Iterable if you just need iteration, for (String s : strings):
Iterable<String> strings = new ArrayList<>();
// Collection if you also need .size() or .stream():
Collection<String> strings = new ArrayList<>();
// List if you also need .get(index):
List<String> strings = new ArrayList<>();
// Don't declare a specific list implementation
// unless you're sure you need it:
ArrayList<String> strings = new ArrayList<>(); // You don't need ArrayList
另一个例子是总是声明变量a InputStream
即使它通常是一个 FileInputStream
或者a BufferedInputStream
,因为有一天你或其他人会想要使用其他一些 InputStream
。
如果您需要一个大小为1的简单列表:
List<String> strings = new ArrayList<String>(Collections.singletonList("A"));
如果需要几个对象的列表:
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
同 番石榴 你可以写:
ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");
在Guava中还有其他有用的静态构造函数。你可以阅读它们 这里。
集合文字没有进入Java 8,但是可以使用Stream API在一个相当长的行中初始化列表:
List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());
如果你需要确保你的 List
是一个 ArrayList
:
ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");