我想创建一个用于测试目的的选项列表。起初,我这样做了:
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");
你可以连接 StreamS:
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");