Mac*_*rse 2626 java collections initialization arraylist
我想创建一个用于测试目的的选项列表.起初,我这样做了:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
Run Code Online (Sandbox Code Playgroud)
然后我重构代码如下:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?
Tom*_*Tom 2058
如果你只是声明它是一个更简单List
- 它必须是一个ArrayList吗?
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Run Code Online (Sandbox Code Playgroud)
或者,如果您只有一个元素:
List<String> places = Collections.singletonList("Buenos Aires");
Run Code Online (Sandbox Code Playgroud)
这意味着它places
是不可变的(尝试更改它将导致UnsupportedOperationException
抛出异常).
要ArrayList
创建一个具体的可变列表,您可以ArrayList
从不可变列表创建一个:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Run Code Online (Sandbox Code Playgroud)
coo*_*ird 1935
实际上,初始化的"最佳"方法可能ArrayList
是您编写的方法,因为它不需要以List
任何方式创建新方法:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
Run Code Online (Sandbox Code Playgroud)
问题是,引用该list
实例需要进行相当多的输入.
还有其他选择,例如使用实例初始化程序创建匿名内部类(也称为"双括号初始化"):
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Run Code Online (Sandbox Code Playgroud)
但是,我不太喜欢那种方法,因为你最终得到的是一个子类,ArrayList
它有一个实例初始化器,而这个类只是为了创建一个对象而创建 - 这对我来说似乎有些过分.
什么本来不错了,如果集合字面建议的项目硬币被接受(它被提名在Java 7中推出,但它不太可能成为Java 8任一部分.):
List<String> list = ["A", "B", "C"];
Run Code Online (Sandbox Code Playgroud)
不幸的是,它不会帮助你,因为它会初始化一个不可变的List
而不是一个ArrayList
,而且,它还没有,如果它将会是.
Chr*_*röm 809
在Java 9或更高版本中:
var strings = List.of("foo", "bar", "baz");
Run Code Online (Sandbox Code Playgroud)
这将给你一个不可变的List
,所以它不能改变.
在您预先填充它的大多数情况下,这是您想要的.
List<String> strings = List.of("foo", "bar", "baz");
Run Code Online (Sandbox Code Playgroud)
这将为您List
提供数组支持,因此无法更改长度.
但你可以打电话List.set
,所以它仍然是可变的.
Arrays.asList
静态导入可以缩短甚至更短:
List<String> strings = Arrays.asList("foo", "bar", "baz");
Run Code Online (Sandbox Code Playgroud)
静态导入:
List<String> strings = asList("foo", "bar", "baz");
Run Code Online (Sandbox Code Playgroud)
任何现代IDE都会建议并自动为您做.
例如,在IntelliJ IDEA中,按,Alt+Enter
然后选择Static import method...
.
但是,我不建议缩短Java 9 List.of
方法,因为刚刚of
变得混乱.
List.of
已经很短了,读得很好.
Stream
s为什么它必须是一个List
?
使用Java 8或更高版本,您可以使用Stream
更灵活的:
import static java.util.Arrays.asList;
Run Code Online (Sandbox Code Playgroud)
你可以连接Stream
s:
Stream<String> strings = Stream.of("foo", "bar", "baz");
Run Code Online (Sandbox Code Playgroud)
或者你可以从a Stream
到List
:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
Run Code Online (Sandbox Code Playgroud)
但最好是只使用Stream
而不将其收集到List
.
java.util.ArrayList
(你可能没有.)
引用JEP 269(强调我的):
有一小部分用于初始化可变集合实例与一组预定义值的使用情况.通常最好将这些预定义值放在不可变集合中,然后通过复制构造函数初始化可变集合.
如果你想既预填充的ArrayList
,并添加到它之后(为什么?),使用
import static java.util.stream.Collectors.toList;
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
Run Code Online (Sandbox Code Playgroud)
或者在Java 8或更早版本中:
ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
Run Code Online (Sandbox Code Playgroud)
或使用Stream
:
ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
Run Code Online (Sandbox Code Playgroud)
但同样,最好Stream
直接使用而不是将其收集到List
.
你说你声明的列表作为ArrayList
在你的代码,但只应做,如果你正在使用的一些成员ArrayList
,这不是在List
.
你很可能不会这样做.
通常你应该只需要声明通过通用接口变量,你要使用(例如Iterable
,Collection
或List
),并与具体的实施对它们进行初始化(例如ArrayList
,LinkedList
或Arrays.asList()
).
否则,您将代码限制为特定类型,并且在您需要时更难更改.
例如,如果您要传递ArrayList
给void method(...)
:
import static java.util.stream.Collectors.toCollection;
ArrayList<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
Run Code Online (Sandbox Code Playgroud)
另一个例子是总是声明变量,InputStream
即使它通常是a FileInputStream
或a BufferedInputStream
,因为有一天你或其他人会想要使用其他类型的变量InputStream
.
Ran*_*yaa 108
如果您需要一个大小为1的简单列表:
List<String> strings = new ArrayList<String>(Collections.singletonList("A"));
Run Code Online (Sandbox Code Playgroud)
如果需要多个对象的列表:
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
Run Code Online (Sandbox Code Playgroud)
Paw*_*ski 55
使用番石榴,你可以写:
ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");
Run Code Online (Sandbox Code Playgroud)
在Guava中还有其他有用的静态构造函数.你可以在这里阅读它们.
Mar*_*ark 32
集合文字没有进入Java 8,但是可以使用Stream API在一个相当长的行中初始化列表:
List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
如果你需要确保你List
是ArrayList
:
ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
Run Code Online (Sandbox Code Playgroud)
Geo*_*rge 29
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
Run Code Online (Sandbox Code Playgroud)
Nam*_*man 24
随着Java 9
,如建议JDK增强提案- 269,这可以实现使用收集文字现在为-
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("A", "B", "C");
Run Code Online (Sandbox Code Playgroud)
此外,类似的方法也适用于Map
-
Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")
Run Code Online (Sandbox Code Playgroud)
这与@coobird所述的Collection Literals 提案类似.在JEP文件中进一步澄清 -
备择方案
语言变化已被多次考虑,并被拒绝:
Related => 在Java 9中重载的方便工厂方法的重点是什么
Jor*_*dão 22
您可以创建工厂方法:
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");
Run Code Online (Sandbox Code Playgroud)
但它并不比你的第一次重构好多少.
为了更大的灵活性,它可以是通用的:
public static <T> ArrayList<T> createArrayList(T ... elements) {
ArrayList<T> list = new ArrayList<T>();
for (T element : elements) {
list.add(element);
}
return list;
}
Run Code Online (Sandbox Code Playgroud)
Moh*_*agi 15
在Java 9中,我们可以轻松地ArrayList
在一行中初始化:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
Run Code Online (Sandbox Code Playgroud)
要么
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
Run Code Online (Sandbox Code Playgroud)
Java 9的这种新方法与以前的方法相比具有许多优点:
有关更多详细信息,请参阅此文章 - > List.of和Arrays.asList有什么区别?
小智 8
只需使用以下代码如下.
List<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Run Code Online (Sandbox Code Playgroud)
使用Eclipse Collections(以前的GS Collections),您可以编写以下内容:
List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
Run Code Online (Sandbox Code Playgroud)
您还可以更具体地了解类型以及它们是可变的还是不可变的.
MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Run Code Online (Sandbox Code Playgroud)
你也可以用套装和包包做同样的事情:
Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Run Code Online (Sandbox Code Playgroud)
注意:我是Eclipse Collections的提交者.
关于最紧凑的方法是:
Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
Run Code Online (Sandbox Code Playgroud)
这是另一种方式:
List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
(应该是评论,但是太长了,所以新回复).正如其他人所提到的,该Arrays.asList
方法是固定大小的,但这不是唯一的问题.它也不能很好地处理继承.例如,假设您有以下内容:
class A{}
class B extends A{}
public List<A> getAList(){
return Arrays.asList(new B());
}
Run Code Online (Sandbox Code Playgroud)
上面导致编译器错误,因为List<B>
(即Arrays.asList返回的内容)不是其子类List<A>
,即使您可以将B类型的List<A>
对象添加到对象中.要解决这个问题,您需要执行以下操作:
new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))
Run Code Online (Sandbox Code Playgroud)
这可能是最好的方法,特别是.如果你需要一个无界的列表或需要使用继承.
List<String> names = Arrays.asList("2", "@2234", "21", "11");
Run Code Online (Sandbox Code Playgroud)
您可以使用以下语句:
String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);
Run Code Online (Sandbox Code Playgroud)
像汤姆说:
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Run Code Online (Sandbox Code Playgroud)
但是既然你抱怨想要一个ArrayList,你首先应该知道ArrayList是List的子类,你可以简单地添加这一行:
ArrayList<String> myPlaces = new ArrayList(places);
Run Code Online (Sandbox Code Playgroud)
虽然,这可能会让你抱怨'表现'.
在这种情况下,它对我来说没有意义,为什么,因为你的列表是预定义的,它没有被定义为一个数组(因为在初始化时已知大小).如果这是你的选择:
String[] places = {"Buenos Aires", "Córdoba", "La Plata"};
Run Code Online (Sandbox Code Playgroud)
如果您不关心次要的性能差异,那么您也可以非常简单地将数组复制到ArrayList:
ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));
Run Code Online (Sandbox Code Playgroud)
好的,但是将来你需要的不仅仅是地名,还需要国家代码.假设这仍然是一个在运行时永远不会改变的预定义列表,那么使用一个enum
集合是合适的,如果将来需要更改列表,则需要重新编译.
enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}
Run Code Online (Sandbox Code Playgroud)
会成为:
enum Places {
BUENOS_AIRES("Buenos Aires",123),
CORDOBA("Córdoba",456),
LA_PLATA("La Plata",789);
String name;
int code;
Places(String name, int code) {
this.name=name;
this.code=code;
}
}
Run Code Online (Sandbox Code Playgroud)
Enum有一个静态values
方法,它返回一个数组,其中包含枚举的所有值,例如:
for (Places p:Places.values()) {
System.out.printf("The place %s has code %d%n",
p.name, p.code);
}
Run Code Online (Sandbox Code Playgroud)
在那种情况下,我猜你不需要你的ArrayList.
PS Randyaa演示了另一种使用静态实用程序方法Collections.addAll的好方法.
Java 9具有以下创建不可变列表的方法:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
Run Code Online (Sandbox Code Playgroud)
如果需要,它很容易适应创建一个可变列表:
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
Run Code Online (Sandbox Code Playgroud)
类似的方法可用于Set
和Map
.
有多种方法可以在一行中创建和初始化列表。一些例子:
//Using Double brace initialization, creates a new (anonymous) subclass of ArrayList
List<String> list1 = new ArrayList<>() {{ add("A"); add("B"); }};
//Immutable List
List<String> list2 = List.of("A", "B");
//Fixed size list. Can't add or remove element, though replacing the element is allowed.
List<String> list3 = Arrays.asList("A", "B");
//Modifiable list
List<String> list4 = new ArrayList<>(Arrays.asList("A", "B"));
//Using Java Stream, no guarantees on the type, mutability, serializability, or thread-safety
List<String> list5 = Stream.of("A", "B").collect(Collectors.toList());
//Thread safe List
List<String> list6 = new CopyOnWriteArrayList<>(Arrays.asList("A", "B"));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2863543 次 |
最近记录: |