在一行中初始化ArrayList

时间:2009-06-17 04:10:20

标签: java collections arraylist initialization

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

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

有更好的方法吗?

34 个答案:

答案 0 :(得分:1954)

如果你只是将它声明为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"));

答案 1 :(得分:1838)

实际上,初始化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 proposal Project Coin被接受(它将在Java 7中引入,但它不可能也是Java 8的一部分,那么本来不错的是。):< / p>

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

不幸的是,它不会对你有帮助,因为它会初始化一个不可变的List而不是ArrayList,而且,它还没有,如果有的话。

答案 2 :(得分:748)

简单的答案

在Java 10,11,12或更高版本中:

var strings = List.of("foo", "bar", "baz");

在Java 9或更高版本中:

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

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


Java 8或更早版本:

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

这将为您提供由数组支持的List,因此无法更改长度 但你可以打电话给List.set,所以它仍然是可变的。


您可以使用静态导入使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 s

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

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

您可以连接Stream s:

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

或者您可以从Stream转到List

import static java.util.stream.Collectors.toList;

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

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


如果确实特别需要java.util.ArrayList

(你可能没有。)
引用JEP 269(强调我的):

  

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


如果您希望两者预先填充ArrayList 之后添加(为什么?),请使用

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

或Java 8或更早版本:

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

或使用Stream

import static java.util.stream.Collectors.toCollection;

ArrayList<String> strings = Stream.of("foo", "bar")
                             .collect(toCollection(ArrayList::new));
strings.add("baz");

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


编程到接口,而不是实现

您说您已在代码中将列表声明为ArrayList,但只有当您使用ArrayList中不属于List的{​​{1}}成员时才应该这样做。

你很可能不会这样做。

通常您应该通过您将要使用的最通用接口(例如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 .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

答案 3 :(得分:106)

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

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

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

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

答案 4 :(得分:54)

使用Guava,您可以写:

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

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

答案 5 :(得分:32)

集合文字没有进入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));

答案 6 :(得分:29)

import com.google.common.collect.ImmutableList;

....

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

答案 7 :(得分:23)

Java 9建议使用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") -

$date ="05-10-2017";
echo Carbon::parse($date)->format('d m Y);

与@coobird所述的JDK Enhancement Proposal - 269类似。在JEP文件中进一步澄清 -

<强>替代

  

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

     

Collection Literals proposal

     

Project Coin Proposal, 29 March 2009

     

Project Coin Proposal, 30 March 2009

     

语言   提议被搁置,而不是基于图书馆的提案   在此JEP 186 discussion on lambda-dev, January-March 2014

中进行了总结

相关=&gt; message.

答案 8 :(得分: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");

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

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

public static <T> ArrayList<T> createArrayList(T ... elements) {
  ArrayList<T> list = new ArrayList<T>();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}

答案 9 :(得分:15)

在Java 9中,我们可以轻松地在一行中初始化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"));

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

  1. Space Efficiency
  2. Immutability
  3. Thread Safe
  4. 有关详细信息,请参阅此帖子 - &gt; What is the difference between List.of and Arrays.asList?

答案 10 :(得分: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");

你也可以用套装和包包做同样的事情:

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

答案 11 :(得分:7)

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

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

答案 12 :(得分:7)

关于最简洁的方法是:

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

答案 13 :(得分:7)

这是另一种方式:

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

答案 14 :(得分:6)

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

class A{}
class B extends A{}

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

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

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

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

答案 15 :(得分:6)

您可以使用以下声明:

代码段:

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

List<String> names = Arrays.asList(arr);

答案 16 :(得分:5)

Tom said

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

Enum有一个静态values方法,它返回一个数组,其中包含枚举的所有值,例如:

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

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

P.S。 Randyaa demonstrated另一种使用静态实用程序方法Collections.addAll的好方法。

答案 17 :(得分: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可以使用类似的方法。

答案 18 :(得分:4)

List<String> names = Arrays.asList("2","@2234","21","11");

答案 19 :(得分:4)

您可以使用Cactoos中的StickyList

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

答案 20 :(得分:3)

尝试使用此代码行:

Collections.singletonList(provider)

答案 21 :(得分:3)

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

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

答案 22 :(得分: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编译它。

答案 23 :(得分:1)

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

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

答案 24 :(得分: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的开发者。

答案 25 :(得分: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);
    }
}

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

答案 26 :(得分:1)

Collections.singletonList(messageBody)

如果您需要列出一个项目

集合来自 java.util 包。

答案 27 :(得分:0)

为什么不制作一个简单的实用功能呢?

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

class Example { ... } ”代表“文字列表”。

var Example = /** @class */ (function () {
  function Example() {
  }
  return Example;
}());

答案 28 :(得分:0)

有趣的是,没有一个带有其他重载的衬里 Stream::collect 方法未列出

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

答案 29 :(得分:0)

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

答案 30 :(得分:-1)

我正在从静态上下文中先于路径存储的xml文件中创建messageTemplate列表

public final class TemplateStore {

    private TemplateStore(){}

    private static final String [] VERSIONS = {"081"};
    private static final String TEMPLATE_FILE_MASK = "template/EdiTemplates_v%s.xml";
    private static final String ERROR = "Error In Building Edifact Message Template Store";

    public static final List<MessageTemplate> TEMPLATE_LIST = Arrays.stream(VERSIONS)
            .map(version -> TemplateStore.class
                    .getClassLoader().getResourceAsStream(String.format(TEMPLATE_FILE_MASK, version)))
            .map(inputStream -> {
                try {
                    return ((EdiTemplates) JAXBContext.newInstance(EdiTemplates.class).createUnmarshaller()
                            .unmarshal(inputStream)).getMessageTemplate();
                } catch (JAXBException e) {
                    throw new IllegalArgumentException(ERROR, e);
                }})
            .flatMap(Collection::stream)
            .collect(Collectors.toList());
}

答案 31 :(得分:-1)

尝试一下:

Arrays.asList("yellow", "green","blue");
Collections.singletonList(new String[]{"yellow", "green","blue"});
Arrays.stream((new String[]{"yellow", "green", "blue"})).collect(Collectors.toList());

答案 32 :(得分:-2)

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

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

答案 33 :(得分:-4)

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

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

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