首页 文章

在一行中初始化ArrayList

提问于
浏览
2320

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

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

有一个更好的方法吗?

30 回答

  • 6
    import com.google.common.collect.ImmutableList;
    
    ....
    
    List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
    
  • 5

    这是代码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的开发人员 .

  • 4

    您可以创建工厂方法:

    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;
    }
    
  • 7
    public static <T> List<T> asList(T... a) {
        return new ArrayList<T>(a);
    }
    

    这是 Arrays.asList 的实现,所以你可以去

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

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

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

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

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

    附: Randyaa demonstrated另一个使用静态实用程序方法Collections.addAll的好方法 .

  • 7

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

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

    ll " stands for "文字列表” .

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

    (应该是评论,但是太长了,所以新回复) . 正如其他人提到的那样, Arrays.asList 方法是固定大小的,但是's not the only issue with it. It also doesn' t非常好地处理继承 . 例如,假设您有以下内容:

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

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

  • 7

    关于最紧凑的方法是:

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

    您可以使用Cactoos中的 StickyList

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

    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 .

  • 4

    使用Eclipse Collections(以前为GS Collections),您可以编写以下内容:

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

    您还可以更具体地了解类型以及它们是Mutable还是Immutable .

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

    Note: 我是Eclipse Collections的提交者 .

  • 0

    使用Guava,你可以写:

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

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

  • 654

    最好的方法:

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

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

  • 1835

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

    如果Project CoinProject Coin被接受(它将在Java 7中引入,但它也不可能成为Java 8的一部分),本来会很好的 . ):

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

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

  • 1

    简单的答案

    在Java 8或更早版本中:

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

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


    在Java 9中:

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

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


    答案较短

    您可以使用静态导入使 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 已经够短了,读起来也不错 .


    使用流

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

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

    你可以连接 Stream

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

    或者你可以从 StreamList

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

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


    如果你真的特别需要一个java.util.ArrayList

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

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


    如果您想预先填充 ArrayList 并在之后添加(为什么?),请使用

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

    或者在Java 9中:

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

    或使用 Stream

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

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


    编程到接口,而不是实现

    你说你已经在你的代码中将列表声明为 ArrayList ,但是如果你使用 ArrayList 中不属于 List 的某个成员,你应该这样做 .

    你很可能不会这样做 .

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

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

    例如:

    // Iterable if you just need iteration, for (String s : strings):
    Iterable<String> strings = new ArrayList<>();   
    
    // Collection if you also need .size() or .stream():
    Collection<String> strings = new ArrayList<>(); 
    
    // List if you also need .get(index):
    List<String> strings = new ArrayList<>();       
    
    // Don't declare a specific list implementation
    // unless you're sure you need it:
    ArrayList<String> strings = new ArrayList<>();  // You don't need ArrayList
    
    // Java 10 makes this moot:
    var strings = new ArrayList<String>();
    

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

  • 32

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

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

    在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的这种新方法与以前的方法相比具有许多优点:

    有关更多详细信息,请参阅此帖子 - > What is the difference between List.of and Arrays.asList?

  • 3

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

    您可以使用以下语句:

    代码段:

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

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

  • 104
    Collections.singletonList(messageBody)
    

    如果你需要一个 one item 的清单!

    集合来自java.util包 .

  • 22

    使用 Java 9 ,如JDK Enhancement Proposal - 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所述的Collection Literals proposal相似 . 在JEP文件中进一步澄清 -


    Alternatives

    语言变化被多次考虑并被拒绝:项目硬币提案,2009年3月29日项目硬币提案,2009年3月30日JEP 186关于lambda-dev的讨论,2014年1月至3月语言提案被搁置优先于图书馆 - 本消息中总结的基于提案的提案 .

    进一步阅读=> What is the point of overloaded Convenience Factory Methods for Collections in Java 9

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

    如果你只是将它声明为 List 会更简单 - 它必须是一个ArrayList吗?

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

    或者,如果您只有一个元素:

    List<String> places = Collections.singletonList("Buenos Aires");
    

    这意味着 placesimmutable (尝试更改它将导致抛出 UnsupportedOperationException 异常) .

    要创建一个具体 ArrayList 的可变列表,您可以从不可变列表中创建 ArrayList

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

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

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

    只需使用以下代码如下 .

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

    这是另一种方式:

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

    在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编译它 .

  • 5

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

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

    如果你需要几个对象的列表:

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

    尝试使用此代码行:

    Collections.singletonList(provider)
    

相关问题