【问题标题】:ArrayList initialization equivalent to array initialization [duplicate]ArrayList初始化等效于数组初始化[重复]
【发布时间】:2011-02-15 04:51:22
【问题描述】:

我知道您可以在实例化期间初始化数组,如下所示:

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

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

【问题讨论】:

    标签: java arrays initialization arraylist


    【解决方案1】:

    是的。

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

    这实际上是在创建一个派生自ArrayList&lt;String&gt; 的类(外部大括号执行此操作),然后声明一个静态初始化程序(内部大括号集)。这实际上是包含类的 inner 类,因此它会有一个隐含的this 指针。除非您想对其进行序列化,或者您希望外部类被垃圾回收,否则这不是问题。

    我知道 Java 7 将提供 additional language constructs 来精确地做你想做的事。

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

    【讨论】:

    • 不是我的反对意见,但我认为这是对匿名类的非常讨厌的滥用。至少你不是想把它当作一个特殊功能来传递……
    • 我认为创建匿名类本身并不坏。不过你应该意识到这一点。
    • 我猜它一直被否决,因为它做了 OP 想要避免的事情:对每个元素使用 add()。
    • 我会考虑投反对票,因为创建一个类,只是为了初始化一个对象,让我觉得有点矫枉过正。但是我不是一个足够的java专家来知道这是否是一件坏事。也许在大型程序中创建数千个不必要的类被认为是好的 Java 编码?如果有很多元素,它也非常冗长。与其他建议的答案相比,这种方法有任何优势吗?
    • 它可能已被否决,因为它仅适用于最终值。我同意您的解决方案确实适用于所提出的问题,但您知道有些人在 StackOverflow 上。
    【解决方案2】:
    Arrays.asList("Ryan", "Julie", "Bob");
    

    【讨论】:

      【解决方案3】:

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

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

      让我们从了解发生了什么开始:

      1. 首先,将元素复制到静态工厂Arrays.asList(T...)创建的Arrays.ArrayList&lt;T&gt;中。

        这不会产生与java.lang.ArrayList相同的类,尽管具有相同的简单类名。尽管有一个 List 接口,但它没有实现像 remove(int) 这样的方法。如果你调用这些方法,它会抛出一个UnspportedMethodException。但如果你只需要一个固定大小的列表,你可以在这里停下来。

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

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

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

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

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

      【讨论】:

        【解决方案4】:

        这个怎么样。

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

        【讨论】:

          【解决方案5】:

          这是使用op4j Java 库(1.1. 于 2010 年 12 月发布)的流畅接口完成的:-

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

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

          【讨论】:

            【解决方案6】:

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

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

            你可以更简单:

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

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

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

            【讨论】:

            • asList构造的ArrayList不是java.util.ArrayList,只是共享相同而已。其实不可能,因为 asList 的返回值被指定为一个固定大小的列表,但是一个 ArrayList 必须是可变大小的。
            • 我的立场是正确的。我没有深入了解源代码。
            【解决方案7】:

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

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

            【讨论】:

            • 值得一提的是,除非您严格需要ArrayList,否则最好只使用Arrays#asList 返回的List
            • @maerics,还值得一提的是,Arrays.asList() 返回一个 unmodifiable 集合。 :)
            • Arrays.asList() 返回的列表NOT 不可修改,@kocko。它具有固定大小,但您可以更改引用以指向完全不同的对象,例如Arrays.asList(...).set(0,new String("new string")) 此代码将起作用并将列表的第一个元素设置为值为“新字符串”的字符串对象。事实上,它会直接写入本机数组!绝对不是不可修改的。
            • 为什么人们从来没有在他们的帖子中提到正确的 import/include/require 语句?
            • 因为配置良好的 IDE 将为您编写导入,只要有一个匹配的类,就像这里的情况一样。
            【解决方案8】:

            嗯,在 Java 中,列表没有文字语法,所以你必须使用 .add()。

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

            1. 使用 Groovy 或类似的东西
            2. 使用 Arrays.asList(array)

            2 看起来像:

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

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

            【讨论】:

              猜你喜欢
              • 2018-09-04
              • 1970-01-01
              • 2012-04-30
              • 2011-05-11
              • 2018-08-30
              • 2016-01-29
              • 2014-10-13
              • 1970-01-01
              • 2020-10-24
              相关资源
              最近更新 更多