Java ArrayList 初始化等价于数组初始化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2760995/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 12:32:19  来源:igfitidea点击:

ArrayList initialization equivalent to array initialization

javaarraysinitializationarraylist

提问by Jonathan

I am aware that you can initialize an array during instantiation as follows:

我知道你可以在实例化过程中初始化一个数组,如下所示:

String[] names = new String[] {"Ryan", "Julie", "Bob"};

Is there a way to do the same thing with an ArrayList? Or must I add the contents individually with array.add()?

有没有办法用 ArrayList 做同样的事情?或者我必须单独添加内容array.add()

采纳答案by meriton

Arrays.asListcan help here:

Arrays.asList可以在这里提供帮助:

new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));

回答by jayshao

Well, in Java there's no literal syntax for lists, so you have to do .add().

好吧,在 Java 中,列表没有文字语法,因此您必须使用 .add()。

If you have a lot of elements, it's a bit verbose, but you could either:

如果你有很多元素,它有点冗长,但你可以:

  1. use Groovy or something like that
  2. use Arrays.asList(array)
  1. 使用 Groovy 或类似的东西
  2. 使用 Arrays.asList(array)

2 would look something like:

2 看起来像:

String[] elements = new String[] {"Ryan", "Julie", "Bob"};
List list = new ArrayList(Arrays.asList(elements));

This results in some unnecessary object creation though.

这会导致一些不必要的对象创建。

回答by Brian Agnew

Yes.

是的。

new ArrayList<String>(){{
   add("A");
   add("B");
}}

What this is actually doing is creating a class derived from ArrayList<String>(the outer set of braces do this) and then declare a static initialiser (the inner set of braces). This is actually an innerclass of the containing class, and so it'll have an implicit thispointer. Not a problem unless you want to serialise it, or you're expecting the outer class to be garbage collected.

这实际上是创建一个派生自的类ArrayList<String>(外部大括号执行此操作),然后声明一个静态初始化程序(内部大括号组)。这实际上是包含类的内部类,因此它将有一个隐式this指针。除非你想序列化它,或者你期望外部类被垃圾收集,否则这不是问题。

I understand that Java 7 will provide additional language constructsto do precisely what you want.

我知道 Java 7 将提供额外的语言结构来精确地做你想要的。

EDIT: recent Java versions provide more usable functions for creating such collections, and are worth investigating over the above (provided at a time prior to these versions)

编辑:最近的 Java 版本为创建此类集合提供了更多可用的功能,值得对上述内容进行研究(在这些版本之前的时间提供)

回答by Fred Haslam

Here is the closest you can get:

这是你能得到的最接近的:

ArrayList<String> list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob"));

You can go even simpler with:

您可以更简单地使用:

List<String> list = Arrays.asList("Ryan", "Julie", "Bob")

Looking at the source for Arrays.asList, it constructs an ArrayList, but by default is cast to List. So you could do this (but not reliably for new JDKs):

查看 Arrays.asList 的源代码,它构造了一个 ArrayList,但默认情况下会强制转换为 List。所以你可以这样做(但对于新的 JDK 不可靠):

ArrayList<String> list = (ArrayList<String>)Arrays.asList("Ryan", "Julie", "Bob")

回答by John D

Arrays.asList("Ryan", "Julie", "Bob");

回答by crsedgar

This is how it is done using the fluent interface of the op4jJava library (1.1. was released Dec '10) :-

这是使用op4jJava 库(1.1. 于 10 年 12 月发布)的流畅接口完成的方式:-

List<String> names = Op.onListFor("Ryan", "Julie", "Bob").get();

It's a very cool library that saves you a tonne of time.

这是一个非常酷的库,可为您节省大量时间。

回答by Ken de Guzman

How about this one.

这个怎么样。

ArrayList<String> names = new ArrayList<String>();
Collections.addAll(names, "Ryan", "Julie", "Bob");

回答by NameSpace

The selected answer is: ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));

选择的答案是: ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));

However, its important to understand the selected answer internally copies the elements several times before creating the final array, and that there is a way to reduce some of that redundancy.

但是,在创建最终数组之前了解所选答案在内部多次复制元素很重要,并且有一种方法可以减少一些冗余。

Lets start by understanding what is going on:

让我们首先了解发生了什么:

  1. First, the elements are copied into the Arrays.ArrayList<T>created by the static factory Arrays.asList(T...).

    This does not the produce the same class as java.lang.ArrayListdespite having the same simple class name. It does not implement methods like remove(int)despite having a List interface. If you call those methods it will throw an UnspportedMethodException. But if all you need is a fixed-sized list, you can stop here.

  2. Next the Arrays.ArrayList<T>constructed in #1 gets passed to the constructor ArrayList<>(Collection<T>)where the collection.toArray()method is called to clone it.

    public ArrayList(Collection<? extends E> collection) {
    ......
    Object[] a = collection.toArray();
    }
    
  3. Next the constructor decides whether to adopt the cloned array, or copy it again to remove the subclass type. Since Arrays.asList(T...)internally uses an array of type T, the very same one we passed as the parameter, the constructor always rejects using the clone unless T is a pure Object. (E.g. String, Integer, etc all get copied again, because they extend Object).

    if (a.getClass() != Object[].class) {      
        //Arrays.asList(T...) is always true here 
        //when T subclasses object
        Object[] newArray = new Object[a.length];
        System.arraycopy(a, 0, newArray, 0, a.length);
        a = newArray;
    }
    array = a;
    size = a.length;
    
  1. 首先,元素被复制到Arrays.ArrayList<T>由静态工厂创建的Arrays.asList(T...)

    java.lang.ArrayList尽管具有相同的简单类名,但这不会产生相同的类。remove(int)尽管有 List 接口,但它没有实现类似的方法。如果你调用这些方法,它会抛出一个UnspportedMethodException. 但是,如果您只需要一个固定大小的列表,则可以到此为止。

  2. 接下来Arrays.ArrayList<T>,#1 中构造的被传递给构造函数ArrayList<>(Collection<T>),在该构造函数中collection.toArray()调用该方法来克隆它。

    public ArrayList(Collection<? extends E> collection) {
    ......
    Object[] a = collection.toArray();
    }
    
  3. 接下来构造函数决定是采用克隆的数组,还是再次复制它以删除子类类型。由于Arrays.asList(T...)内部使用 T 类型的数组,与我们作为参数传递的数组相同,构造函数总是拒绝使用克隆,除非 T 是纯对象。(例如,字符串、整数等都被再次复制,因为它们扩展了对象)。

    if (a.getClass() != Object[].class) {      
        //Arrays.asList(T...) is always true here 
        //when T subclasses object
        Object[] newArray = new Object[a.length];
        System.arraycopy(a, 0, newArray, 0, a.length);
        a = newArray;
    }
    array = a;
    size = a.length;
    

Thus, our data was copied 3x just to explicitly initialize the ArrayList. We could get it down to 2x if we force Arrays.AsList(T...)to construct an Object[] array, so that ArrayList can later adopt it, which can be done as follows:

因此,我们的数据被复制了 3 次,只是为了显式初始化 ArrayList。如果我们强制Arrays.AsList(T...)构造一个 Object[] 数组,我们可以将其降低到 2 倍,以便 ArrayList 以后可以采用它,这可以按如下方式完成:

(List<Integer>)(List<?>) new ArrayList<>(Arrays.asList((Object) 1, 2 ,3, 4, 5));

Or maybe just adding the elements after creation might still be the most efficient.

或者在创建后添加元素可能仍然是最有效的。