Java 在一行中初始化 ArrayList
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1005073/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Initialization of an ArrayList in one line
提问by Macarse
I wanted to create a list of options for testing purposes. At first, I did this:
我想创建一个用于测试目的的选项列表。起初,我是这样做的:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
Then, I refactored the code as follows:
然后,我将代码重构如下:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Is there a better way to do this?
有一个更好的方法吗?
采纳答案by coobird
Actually, probably the "best" way to initialize the ArrayList
is the method you wrote, as it does not need to create a new List
in any way:
实际上,初始化它的“最佳”方法可能ArrayList
是您编写的方法,因为它不需要以List
任何方式创建新方法:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
The catch is that there is quite a bit of typing required to refer to that list
instance.
问题是引用该list
实例需要大量的输入。
There are alternatives, such as making an anonymous inner class with an instance initializer (also known as an "double brace initialization"):
还有其他选择,例如使用实例初始化程序(也称为“双括号初始化”)创建匿名内部类:
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
However, I'm not too fond of that method because what you end up with is a subclass of ArrayList
which has an instance initializer, and that class is created just to create one object -- that just seems like a little bit overkill to me.
但是,我不太喜欢那个方法,因为你最终得到的是一个子类,ArrayList
它有一个实例初始值设定项,而创建那个类只是为了创建一个对象——这对我来说似乎有点过头了。
What would have been nice was if the Collection Literals proposalfor Project Coinwas accepted (it was slated to be introduced in Java 7, but it's not likely to be part of Java 8 either.):
什么本来不错了,如果集合字面建议的项目硬币被接受(它被提名在Java 7中推出,但它不太可能成为Java 8任一部分。):
List<String> list = ["A", "B", "C"];
Unfortunately it won't help you here, as it will initialize an immutable List
rather than an ArrayList
, and furthermore, it's not available yet, if it ever will be.
不幸的是,它在这里对您没有帮助,因为它会初始化一个不可变的List
而不是一个ArrayList
,此外,它还不可用,如果有的话。
回答by Tom
It would be simpler if you were to just declare it as a List
- does it have to be an ArrayList?
如果你只是将它声明为 a 会更简单List
- 它必须是一个 ArrayList 吗?
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Or if you have only one element:
或者,如果您只有一个元素:
List<String> places = Collections.singletonList("Buenos Aires");
This would mean that places
is immutable(trying to change it will cause an UnsupportedOperationException
exception to be thrown).
这意味着它places
是不可变的(尝试更改它会导致UnsupportedOperationException
抛出异常)。
To make a mutable list that is a concrete ArrayList
you can create an ArrayList
from the immutable list:
要制作一个具体的可变列表,ArrayList
您可以ArrayList
从不可变列表中创建一个:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
回答by Jord?o
You could create a factory method:
您可以创建一个工厂方法:
public static ArrayList<String> createArrayList(String ... elements) {
ArrayList<String> list = new ArrayList<String>();
for (String element : elements) {
list.add(element);
}
return list;
}
....
ArrayList<String> places = createArrayList(
"S?o Paulo", "Rio de Janeiro", "Brasília");
But it's not much better than your first refactoring.
但这并不比您的第一次重构好多少。
For greater flexibility, it can be generic:
为了更大的灵活性,它可以是通用的:
public static <T> ArrayList<T> createArrayList(T ... elements) {
ArrayList<T> list = new ArrayList<T>();
for (T element : elements) {
list.add(element);
}
return list;
}
回答by George
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
回答by Christoffer Hammarstr?m
The simple answer
简单的答案
In Java 9or later, after List.of()
was added:
在Java 9或更高版本中,List.of()
添加后:
List<String> strings = List.of("foo", "bar", "baz");
With Java 10or later, this can be shortened with the var
keyword.
对于Java 10或更高版本,可以使用var
关键字缩短此时间。
var strings = List.of("foo", "bar", "baz");
This will give you an immutableList
, so it cannot be changed.
Which is what you want in most cases where you're prepopulating it.
这会给你一个不可变的List
,所以它不能改变。
在预填充它的大多数情况下,这就是您想要的。
Java 8 or earlier:
Java 8 或更早版本:
List<String> strings = Arrays.asList("foo", "bar", "baz");
This will give you a List
backed by an array, so it cannot change length.
But you can call List.set
, so it's still mutable.
这会给你一个List
数组支持,所以它不能改变长度。
但是您可以调用List.set
,因此它仍然是可变的。
You can make Arrays.asList
even shorter with a static import:
您可以Arrays.asList
使用静态导入更短:
List<String> strings = asList("foo", "bar", "baz");
The static import:
静态导入:
import static java.util.Arrays.asList;
Which any modern IDE will suggest and automatically do for you.
For example in IntelliJ IDEA you press Alt+Enter
and select Static import method...
.
任何现代 IDE 都会建议并自动为您执行。
例如,在 IntelliJ IDEA 中,您按下Alt+Enter
并选择Static import method...
。
However, i don't recommend shortening the List.of
method to of
, because that becomes confusing.List.of
is already short enough and reads well.
但是,我不建议将List.of
方法缩短为of
,因为这会变得混乱。List.of
已经足够短并且读起来很好。
Using Stream
s
使用Stream
s
Why does it have to be a List
?
With Java 8 or later you can use a Stream
which is more flexible:
为什么它必须是一个List
?
在 Java 8 或更高版本中,您可以使用Stream
更灵活的 a:
Stream<String> strings = Stream.of("foo", "bar", "baz");
You can concatenate Stream
s:
您可以连接Stream
s:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
Or you can go from a Stream
to a List
:
或者您可以从 aStream
转到 a List
:
import static java.util.stream.Collectors.toList;
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
But preferably, just use the Stream
without collecting it to a List
.
但最好只使用Stream
而不将其收集到List
.
If you reallyspecifically need a java.util.ArrayList
如果你真的特别需要一个java.util.ArrayList
(You probably don't.)
To quote JEP 269(emphasis mine):
(你可能没有。)
引用JEP 269(强调我的):
There is a small setof use cases for initializing a mutable collection instance with a predefined set of values. It's usually preferable to have those predefined values be in an immutable collection, and then to initialize the mutable collection via a copy constructor.
有一小部分用于初始化可变集合实例与一组预定义值的使用情况。通常最好将这些预定义值放在不可变集合中,然后通过复制构造函数初始化可变集合。
If you want to bothprepopulate an ArrayList
andadd to it afterwards (why?), use
如果你想既预填充的ArrayList
,并添加到它之后(为什么?),使用
ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
or in Java 8 or earlier:
或在 Java 8 或更早版本中:
ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
or using Stream
:
或使用Stream
:
import static java.util.stream.Collectors.toCollection;
ArrayList<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
But again, it's better to just use the Stream
directly instead of collecting it to a List
.
但同样,最好Stream
直接使用而不是将其收集到List
.
Program to interfaces, not to implementations
编程接口,而不是实现
You said you've declared the list as an ArrayList
in your code, but you should only do that if you're using some member of ArrayList
that's not in List
.
您说您已ArrayList
在代码中将该列表声明为 an ,但只有在您使用的某个成员ArrayList
不在List
.
Which you are most likely not doing.
你最有可能不这样做。
Usually you should just declare variables by the most general interface that you are going to use (e.g. Iterable
, Collection
, or List
), and initialize them with the specific implementation (e.g. ArrayList
, LinkedList
or Arrays.asList()
).
通常,您应该仅通过将要使用的最通用接口(例如Iterable
、Collection
、 或List
)声明变量,并使用特定实现(例如ArrayList
、LinkedList
或Arrays.asList()
)初始化它们。
Otherwise you're limiting your code to that specific type, and it'll be harder to change when you want to.
否则,您会将您的代码限制为该特定类型,并且在您需要时更难更改。
For example, if you're passing an ArrayList
to a void method(...)
:
例如,如果您将 an 传递ArrayList
给 a void method(...)
:
// 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 .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
}
Another example would be always declaring variable an InputStream
even though it is usually a FileInputStream
or a BufferedInputStream
, because one day soon you or somebody else will want to use some other kind of InputStream
.
另一个例子是总是声明变量 an ,InputStream
即使它通常是 aFileInputStream
或 a BufferedInputStream
,因为很快你或其他人有一天会想要使用其他类型的InputStream
.
回答by Randyaa
If you need a simple list of size 1:
如果您需要一个大小为 1 的简单列表:
List<String> strings = new ArrayList<String>(Collections.singletonList("A"));
If you need a list of several objects:
如果您需要多个对象的列表:
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
回答by Dawg
In Java, you can't do
在 Java 中,你不能这样做
ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
As was pointed out, you'd need to do a double brace initialization:
正如所指出的,你需要做一个双括号初始化:
List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};
But this may force you into adding an annotation @SuppressWarnings("serial")
or generate a serial UUID which is annoying. Also most code formatters will unwrap that into multiple statements/lines.
但这可能会迫使您添加注释@SuppressWarnings("serial")
或生成令人讨厌的串行 UUID。此外,大多数代码格式化程序会将其解包为多个语句/行。
Alternatively you can do
或者你可以做
List<String> places = Arrays.asList(new String[] {"x", "y" });
but then you may want to do a @SuppressWarnings("unchecked")
.
但是你可能想要做一个@SuppressWarnings("unchecked")
.
Also according to javadoc you should be able to do this:
另外根据javadoc,你应该能够做到这一点:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
But I'm not able to get it to compile with JDK 1.6.
但我无法让它与 JDK 1.6 一起编译。
回答by abaelter
public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}
This is the implementation of Arrays.asList
, so you could go with
这是 的实现Arrays.asList
,因此您可以使用
ArrayList<String> arr = (ArrayList<String>) Arrays.asList("1", "2");
回答by Adrian
Actually, it's possible to do it in one line:
实际上,可以在一行中完成:
Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})
回答by user439407
(Should be a comment, but too long, so new reply). As others have mentioned, the Arrays.asList
method is fixed size, but that's not the only issue with it. It also doesn't handle inheritance very well. For instance, suppose you have the following:
(应该是评论,但太长了,所以新回复)。正如其他人所提到的,该Arrays.asList
方法是固定大小的,但这并不是它的唯一问题。它也不能很好地处理继承。例如,假设您有以下内容:
class A{}
class B extends A{}
public List<A> getAList(){
return Arrays.asList(new B());
}
The above results in a compiler error, because List<B>
(which is what is returned by Arrays.asList) is not a subclass of List<A>
, even though you can add Objects of type B to a List<A>
object. To get around this, you need to do something like:
上述结果导致编译器错误,因为List<B>
(这是 Arrays.asList 返回的内容)不是 的子类List<A>
,即使您可以将 B 类型的List<A>
对象添加到对象中。要解决此问题,您需要执行以下操作:
new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))
This is probably the best way to go about doing this, esp. if you need an unbounded list or need to use inheritance.
这可能是执行此操作的最佳方式,尤其是。如果您需要无界列表或需要使用继承。