3087

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

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

有一个更好的方法吗?

4

33 回答 33

2432

如果您只是将其声明为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"));
于 2009-06-17T04:15:06.243 回答
2193

实际上,初始化的“最佳”方法可能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具有实例初始化程序的子类,并且创建该类只是为了创建一个对象——这对我来说似乎有点矫枉过正。

如果项目 Coin的Collection Literals 提案被接受,那将是一件好事(它计划在 Java 7 中引入,但它也不太可能成为 Java 8 的一部分。):

List<String> list = ["A", "B", "C"];

不幸的是,它在这里对您没有帮助,因为它将初始化一个不可变的List而不是一个ArrayList,而且,它还不可用,如果有的话。

于 2009-06-17T04:13:36.023 回答
1036

简单的答案

Java 9 或更高版本:

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

这会给你一个不可变 List的,所以它不能改变。
在大多数情况下,这是您预填充它时想要的。

Java 8 或更早版本:

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

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

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

静态导入

您可以使用静态导入使 Java 8Arrays.asList更短:

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

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

我不建议将List.of方法静态导入 just of,因为它很混乱。

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

使用Stream_

为什么它必须是一个List
使用 Java 8 或更高版本,您可以使用Stream更灵活的 a:

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

您可以连接Streams:

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

或者您可以从 aStream转到 a List

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

或在 Java 8 或更早版本中:

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.

*您可能不需要专门的ArrayList. 引用JEP 269

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

(强调我的)

编程接口,而不是实现

您说您已在代码中将列表声明为 an ArrayList,但仅当您使用的某些成员ArrayList不在List.

您很可能不会这样做。

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

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

例如,如果您将 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 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
}

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

于 2010-09-09T12:33:15.437 回答
119

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

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

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

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
于 2011-08-30T04:33:05.330 回答
62

使用Guava,您可以编写:

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

在 Guava 中还有其他有用的静态构造函数。您可以在此处阅读有关它们的信息。

于 2013-07-29T13:24:44.797 回答
44

使用及更高版本,如JEP 269: Convenience Factory Methods for Collections中所建议的那样,现在可以使用集合文字来实现-

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 所述的Collection Literals提案。JEP中也进一步澄清了 -


备择方案

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

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

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

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

语言提案被搁置,优先于本信息中总结的基于库的提案。

相关:Java 9 中集合的重载便利工厂方法有什么意义

于 2017-02-02T17:36:24.513 回答
34

集合文字没有进入 Java 8,但可以使用 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));
于 2014-04-03T23:21:48.067 回答
32
import com.google.common.collect.ImmutableList;

....

List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
于 2010-05-12T13:14:16.830 回答
25

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

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;
}
于 2010-05-04T00:57:54.097 回答
15

ArrayList在 Java 9 中,我们可以在一行中轻松地初始化一个:

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

或者

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

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

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

有关更多详细信息,请参阅这篇文章 -> List.of 和 A​​rrays.asList 有什么区别?

于 2017-10-06T01:16:10.983 回答
9

只需使用以下代码,如下所示。

List<String> list = new ArrayList<String>() {{
            add("A");
            add("B");
            add("C");
}};
于 2013-09-21T09:43:07.897 回答
8

最紧凑的方法是:

Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
于 2014-12-15T11:44:15.160 回答
8

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

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 的提交者。

于 2015-01-28T01:30:35.263 回答
7

(应该是评论,但太长了,所以新回复)。正如其他人所提到的,该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))

这可能是最好的方法,尤其是。如果您需要一个无界列表或需要使用继承。

于 2013-06-06T05:44:26.987 回答
7

这是另一种方式:

List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
于 2017-02-28T22:50:54.430 回答
6

您可以使用以下语句:

代码片段:

String [] arr = {"Sharlock", "Homes", "Watson"};

List<String> names = Arrays.asList(arr);
于 2017-03-28T20:18:03.327 回答
5

就像汤姆说的

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。

PS Randyaa 演示了另一种使用静态实用程序方法Collections.addAll的好方法。

于 2013-06-17T17:57:24.853 回答
5

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

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

于 2016-12-06T09:57:49.613 回答
4
List<String> names = Arrays.asList("2","@2234","21","11");
于 2014-06-22T08:12:31.383 回答
4

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

List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
于 2016-09-13T05:54:55.537 回答
4

您可以StickyListCactoos使用:

List<String> names = new StickyList<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);
于 2017-06-25T17:48:17.560 回答
3

试试这个代码行:

Collections.singletonList(provider)
于 2016-05-16T13:45:01.610 回答
3

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

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

于 2021-05-19T11:35:46.280 回答
2

在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 一起编译。

于 2012-02-13T21:47:34.907 回答
1
Collections.singletonList(messageBody)

如果您需要一个项目的列表!

Collections来自java.util包。

于 2015-04-03T09:30:38.747 回答
1

最好的方法:

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

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

于 2016-07-17T18:31:11.010 回答
1

这是AbacusUtil的代码

// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// Or for Immutable List/Set/Map
ImmutableList.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的开发者。

于 2016-11-28T19:56:37.233 回答
0

对我来说 Arrays.asList() 是最好和方便的。我总是喜欢这样初始化。如果您是 Java 集合的初学者,那么我希望您参考ArrayList 初始化

于 2014-12-07T05:37:12.533 回答
0

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

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");
于 2017-12-04T11:23:08.107 回答
0

有趣的是,没有列出具有其他重载方法的单行代码Stream::collect

ArrayList<String> places = Stream.of( "Buenos Aires", "Córdoba", "La Plata" ).collect( ArrayList::new, ArrayList::add, ArrayList::addAll );
于 2019-10-04T15:04:11.563 回答
0

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

ArrayList<String> allViews = new ArrayList<String>();
Collections.addAll(allViews,"hello","world","abc","def","ghi");
于 2022-02-13T05:55:56.587 回答
-1

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

Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})
于 2013-06-02T13:34:17.930 回答
-5
public static <T> List<T> asList(T... a) {
    return new ArrayList<T>(a);
}

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

ArrayList<String> arr = (ArrayList<String>) Arrays.asList("1", "2");
于 2012-07-31T13:22:58.980 回答