在一行中初始化ArrayList

我想创建一个用于测试目的的选项列表。首先,我这样做:

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"));

有没有更好的方法来做到这一点?

3529778 次浏览

实际上,初始化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的子类,它有一个实例初始化器,并且创建该类只是为了创建一个对象-这对我来说似乎有点矫枉过正。

如果项目币收藏文字提案被接受(它计划在Java7中引入,但它也不太可能成为Java8的一部分):

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"));

并导入正确的包:

import java.util.Arrays;

你可以创建一个工厂方法:

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");

但它并不比你的第一次重构好多少。

为了获得更大的灵活性,它可以是通用的:

public static <T> ArrayList<T> createArrayList(T ... elements) {ArrayList<T> list = new ArrayList<T>();for (T element : elements) {list.add(element);}return list;}
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");

简单的答案

Java9或以后:

List<String> strings = List.of("foo", "bar", "baz");

这将为您提供不可变List,因此无法更改。
在大多数情况下,这就是你想要的,你正在预填充它。

Java8或更早:

List<String> strings = Arrays.asList("foo", "bar", "baz");

这将为您提供一个由数组支持的List*,因此它不能更改长度。
但是你可以调用List.set(...),所以它仍然是可变

*实现细节:它是java.util.Arrays内部的一个私有嵌套类,名为ArrayList
这是一个与java.util.ArrayList不同的类,即使它们的简单名称是相同的。

静态导入

您可以使用静态导入使Java8Arrays.asList更短:

import static java.util.Arrays.asList;...List<String> strings = asList("foo", "bar", "baz");

任何现代IDE*都会建议并为您执行此操作。

我不建议将List.of方法作为of静态导入,因为它会令人困惑。

*例如,在IntelliJ IDEA中,您按Alt+Enter并选择Static import method...

使用Stream

为什么必须是List
使用Java8或更高版本,您可以使用更灵活的Stream

Stream<String> strings = Stream.of("foo", "bar", "baz");

您可以连接Stream

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),Stream.of("baz", "qux"));

或者你可以从StreamList

import static java.util.stream.Collectors.toList;...var strings = Stream.of("foo", "bar", "baz").toList(); // Java 16
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList()); // Java 8

但最好是,只使用Stream而不将其收集到List

如果你需要一个java.util.ArrayList*

如果您想两者预填充ArrayList,请使用

List<String> strings = new ArrayList<>(List.of("foo", "bar"));strings.add("baz");

Java8或更早:

List<String> strings = new ArrayList<>(asList("foo", "bar"));strings.add("baz");

或使用Stream

import static java.util.stream.Collectors.toCollection;
List<String> strings = Stream.of("foo", "bar").collect(toCollection(ArrayList::new));strings.add("baz");

但是,最好直接使用Stream,而不是将其收集到List

*您可能不需要专门的#0。要引用JEP 269:

使用预定义的一组值初始化可变集合实例有一小组用例。通常最好将这些预定义的值放在不可变集合中,然后通过复制构造函数初始化可变集合。

(强调我的)

程序到接口,而不是实现

您说您已经在代码中将列表声明为ArrayList,但只有当您使用ArrayList中不在List中的某个成员时,您才应该这样做。

这是你最有可能不做的。

通常,您应该通过您将要使用的最通用接口(例如IterableCollectionList)声明变量,并使用特定实现(例如ArrayListLinkedListArrays.asList())初始化它们。

否则,您将代码限制为该特定类型,并且在需要时更难更改。

例如,如果您将ArrayList传递给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 random access, .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}

另一个例子是总是将变量声明为InputStream,即使它通常是FileInputStreamBufferedInputStream,因为很快有一天你或其他人会想要使用其他类型的InputStream

如果您需要大小为1的简单列表:

List<String> strings = new ArrayList<String>(Collections.singletonList("A"));

如果您需要多个对象的列表:

List<String> strings = new ArrayList<String>();Collections.addAll(strings,"A","B","C","D");

在Java,你不能

ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

正如所指出的,您需要进行双括号初始化:

List<String> places = new ArrayList<String>() \{\{ add("x"); add("y"); }};

但这可能会迫使您添加注释@SuppressWarnings("serial")或生成令人讨厌的串行UUID。

或者你可以做

List<String> places = Arrays.asList(new String[] {"x", "y" });

然后你可能想做一个@SuppressWarnings("unchecked")

根据javadoc,你应该能够做到这一点:

List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

但是我无法让它用JDK 1.6编译。

public static <T> List<T> asList(T... a) {return new ArrayList<T>(a);}

这是Arrays.asList的实现,因此您可以使用

ArrayList<String> arr = (ArrayList<String>) Arrays.asList("1", "2");

实际上,可以在一行中完成:

Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})

(应该是一个注释,但是太长了,所以新回复)。正如其他人提到的,Arrays.asList方法是固定大小的,但这并不是唯一的问题。它也不能很好地处理继承。例如,假设你有以下内容:

class A{}class B extends A{}
public List<A> getAList(){return Arrays.asList(new B());}

上述结果会导致编译器错误,因为List<B>(Arrays.asList返回的内容)不是List<A>的子类,即使您可以将B类型的对象添加到List<A>对象。要解决这个问题,您需要执行以下操作:

new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))

这可能是执行此操作的最佳方法,特别是如果您需要无界列表或需要使用继承。

喜欢汤姆说

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

但是既然你抱怨想要一个ArrayList,你应该首先知道ArrayList是List的子类,你可以简单地添加这一行:

ArrayList<String> myPlaces = new ArrayList(places);

虽然,这可能会让你抱怨“性能”。

在这种情况下,对我来说没有意义,为什么,因为你的列表是预定义的,它没有定义为数组(因为大小在初始化时是已知的)。如果这是你的选择:

String[] places = {"Buenos Aires", "Córdoba", "La Plata"};

如果你不关心小的性能差异,那么你也可以非常简单地将数组复制到ArrayList:

ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));

好的,但是将来你需要的不仅仅是地名,你还需要一个国家代码。假设这仍然是一个预定义的列表,在运行时永远不会改变,那么使用enum集是合适的,如果将来需要更改列表,这将需要重新编译。

enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}

将成为:

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;}}

枚举有一个静态values方法,它返回一个数组,其中包含枚举的所有值,按照它们声明的顺序,例如:

for (Places p:Places.values()) {System.out.printf("The place %s has code %d%n",p.name, p.code);}

在这种情况下,我猜你不需要你的ArrayList。

P. S.Randyaa展示使用静态实用程序方法Collections.add全部的另一种好方法。

番石榴你可以写:

ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

在Guava中还有其他有用的静态构造函数。您可以阅读它们这里

只需使用下面的代码如下。

List<String> list = new ArrayList<String>() \{\{add("A");add("B");add("C");}};

集合文字没有进入Java8,但可以使用Stream API在一个相当长的行中初始化列表:

List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());

如果您需要确保您的ListArrayList

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
List<String> names = Arrays.asList("2","@2234","21","11");

对我来说Arrays.asList()是最方便的方法,我总是喜欢用这种方式初始化。如果你是一个初学者Java集合,那么我希望你参考ArrayList初始化

做到这一点的最紧凑的方法是:

Double array[] = { 1.0, 2.0, 3.0};List<Double> list = Arrays.asList(array);

使用Eclipse集合,您可以编写以下内容:

List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");

您还可以更具体地说明类型以及它们是可变的还是不可变的。

MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");

您也可以使用Sets和Bags执行相同的操作:

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");

备注:我是Eclipse集合的提交者。

Collections.singletonList(messageBody)

如果你需要一个列表一个项目

收藏来自java.util包。

尝试使用此代码行:

Collections.singletonList(provider)

最好的方法是:

package main_package;
import java.util.ArrayList;

public class Stackkkk {public static void main(String[] args) {ArrayList<Object> list = new ArrayList<Object>();add(list, "1", "2", "3", "4", "5", "6");System.out.println("I added " + list.size() + " element in one line");}
public static void add(ArrayList<Object> list,Object...objects){for(Object object:objects)list.add(object);}}

只需创建一个可以拥有任意数量元素的函数,并调用它将它们添加到一行中。

是的,在数组的帮助下,您可以在一行中初始化数组列表,

List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");

这里是代码算术软件

// ArrayListList<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");// HashSetSet<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");// HashMapMap<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);
// Or for Immutable List/Set/MapImmutableList.of("Buenos Aires", "Córdoba", "La Plata");ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);
// The most efficient way, which is similar with Arrays.asList(...) in JDK.// but returns a flexible-size list backed by the specified array.List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");

声明:我是AbacusUtil的开发者。

Java9有以下方法来创建不可变列表:

List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");

如果需要,可以轻松调整以创建可变列表:

List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

类似的方法可用于SetMap

对于及以上,正如JEP 269:便利工厂收集方法所建议的,现在可以使用集合文字来实现-

List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("A", "B", "C");

类似的方法也适用于Map-

Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")

类似于@coobird所说的收藏文字提案。在JEP中进一步澄清-


替代品

语言更改已被多次考虑,并被拒绝:

项目硬币提案,2009年3月29日

硬币项目提案,2009年3月30日

JEP 186关于lambda-dev的讨论,2014年1-3月

语言建议被搁置,而不是基于图书馆的建议总结在消息。

相关:什么是重载便利工厂方法的集合在Java9

这里有另一种方法:

List<String> values = Stream.of("One", "Two").collect(Collectors.toList());

您可以使用以下语句:

代码片段:

String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);

您可以从仙人掌使用StickyList

List<String> names = new StickyList<>("Scott Fitzgerald", "Fyodor Dostoyevsky");

在Java9中,我们可以在一行中轻松初始化ArrayList

List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");

List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

Java9的这种新方法与以前的方法相比有许多优点:

  1. 空间效率
  2. 不变性
  3. 线程安全

查看更多详情->List.of和Arrays.as有什么区别?

为什么不做一个简单的实用函数来做到这一点呢?

static <A> ArrayList<A> ll(A... a) {ArrayList l = new ArrayList(a.length);for (A x : a) l.add(x);return l;}

ll”代表“文字列表”。

ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");

有趣的是没有一条线与另一条过载Stream::collect方法列出

ArrayList<String> places = Stream.of( "Buenos Aires", "Córdoba", "La Plata" ).collect( ArrayList::new, ArrayList::add, ArrayList::addAll );

使用 Arrays.asList("Buenos Aires", "Córdoba", "La Plata");是正确的。但是任何调用Arrays.asList()的参数为零或只有一个参数都可以替换为调用Collections.singletonList()Collections.emptyList(),这将节省一些内存。

注意:Collections.singletonList()返回的列表是不可变的,而Arrays.asList()返回的列表允许调用set()方法。这可能会在极少数情况下破坏代码。

最简单的方法:您可以使用此方法将多个元素添加到任何类型的集合中,例如ArrayList和HashSet

ArrayList<String> allViews = new ArrayList<String>();Collections.addAll(allViews,"hello","world","abc","def","ghi");