【问题标题】:Pros and cons of using Arrays.asList使用 Arrays.asList 的优缺点
【发布时间】:2012-11-14 07:52:32
【问题描述】:

我想知道使用Arrays.asList 的利弊。在我的代码中使用它时遇到问题。

另外我想知道不使用Arrays.asList将数组转换为数组列表(集合)的最佳方法

【问题讨论】:

  • 你面临的问题是什么。你必须尝试添加一些元素。这在 Arrays.asList 中是不可能的。它只是一个数组周围的列表包装器。
  • @Emil 好点子,在这种情况下new ArrayList<> (Arrays.asList(array)); 可以解决问题。

标签: java arrays collections


【解决方案1】:

要将数组转换为 ArrayList,我会这样做:

new ArrayList<T>(Arrays.asList(myArray));

您需要将列表包装在一个新的 ArrayList 中,否则您将无法添加任何元素,因为 asList() 返回的列表具有固定大小。因此,您在尝试添加元素时会收到 UnsupportedOperationException。

但是如果你不喜欢上面的方法,你也可以这样做:

Collections.addAll(arraylist, array);

两者在性能方面是相当的,据我所知


但更重要的是,您使用第一种方法有什么问题?

【讨论】:

  • 我收到 UnsupportedOperationException。场景是,我不希望重新填充数组。
  • 问题已解决,解决方法有所帮助。我使用“for”循环将数组中的元素添加到列表中。
【解决方案2】:

我想知道使用 Arrays.asList 的优缺点。

主要的“优点”是:

  • 不涉及复制数据,
  • 您的列表将看到在支持数组中所做的任何更改(如果需要)

主要的“缺点”是:

  • 您不能通过“asList”包装器添加或删除元素,
  • 您的列表将看到对支持数组所做的任何更改(如果您不希望这样做)

(还有一个明显的限制:您不能将asList 应用于基元数组。但无论如何转换基元数组并非易事......)


我想知道不使用 Arrays.asList 将数组转换为数组列表(集合)的最佳方法

不使用 aslist 将数组转换为列表的最简单方法是:

new ArrayList<T>(Arrays.asList(arrayOfT))

这样你可能会获得更好的性能:

ArrayList<T> list = new ArrayList<T>(arrayOfT.length);
Collections.addAll(list, arrayOfT);

因为ArrayList&lt;T&gt;(Collection&lt;T&gt;) 构造函数首先调用toArray() 来创建一个临时数组(至少在Java 7 中是这样)。这意味着引擎盖下还有一个额外的副本。

但最重要的是,仅使用 Arrays.asList 比任何避免使用它的方法更简单、更便宜

【讨论】:

    【解决方案3】:

    Arrays.asList 让您可以像查看列表一样查看数组。这意味着将来对数组的更改将影响列表,而对列表的将来更改会影响数组。这是好事还是坏事取决于您打算对 List 做什么,以及您希望它如何与数组关联。

    对于一次性使用,我肯定会选择 Arrays.asList。例如,List 有一个 toString 显示内容,因此 System.out.println(Arrays.asList(myArray)) 可能很有用。

    如果您想保留数组的快照,不受未来更改的影响,我仍然会使用 Arrays.asList,但随后会根据其结果创建一个新 List,如 @NNzz 的上一个回答所示。

    【讨论】:

    • 好久不见!欢迎登机!
    【解决方案4】:

    除了现有的答案,特别是@Stephen C 的一个很好的答案,Arrays.asList 还有一个问题。

    来自Effective Java


    Arrays.asList 从未设计用于将多个参数收集到一个列表中,但是当将可变参数添加到平台时对其进行改造似乎是个好主意。因此,可以执行以下操作:

    List<String> homophones = Arrays.asList("to", ""too", "two");
    

    这种用法有效,但启用它是一个很大的错误。

    在 1.5 版本之前,这是打印数组内容的常用习惯:

    // Obsolete idiom to print an array!
    System.out.println(Arrays.asList(myArray));
    

    这个习惯用法是必要的,因为数组从 Object 继承了它们的 toString 实现,所以直接在数组上调用 toString 会产生一个无用的字符串,例如 [Ljava.lang.Integer;@3e25a5。该习惯用法仅适用于对象引用类型的数组,但如果您不小心尝试了原语数组,程序将无法编译。比如这个程序:

    public static void main(String[] args) {
        int[] digits = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 4 };
        System.out.println(Arrays.asList(digits));
    }
    

    将在 1.4 版中生成此错误消息:

    Va.java:6: 数组中的 asList(Object[]) 不能应用于 (int[]) System.out.println(Arrays.asList(digits));

    由于在 1.5 版中将 Arrays.asList 改装为可变参数方法的不幸决定,该程序现在编译时不会出现错误或警告。

    从好的方面来说,用于将数组转换为字符串的 Arrays.asList 习语现已过时,而当前的习语更加健壮。同样在 1.5 版中,Arrays 类获得了完整的 Arrays.toString 方法(不是 varargs 方法!),专门设计用于将任何类型的数组转换为字符串。如果您使用Arrays.toString 代替Arrays.asList,程序会产生预期的结果:

    // The right way to print an array
    System.out.println(Arrays.toString(myArray));
    

    【讨论】:

      【解决方案5】:

      从 Java 8 开始,我认为创建新数组最简单有效的方法是:

      Stream.of(myArray).collect(Collectors.toList());
      

      最好不要再用了

      new ArrayList<>(Arrays.asList());
      

      因为这是 2 倍的工作量,这会影响内存/性能下降

      关于Arrays.asList,我想几乎所有人都已经解释清楚了。 我想添加更多关于使用 Arrays.asList 的糟糕体验。这已经是很久以前的事了,所以在这一点上可能与某些部分无关。

      在几年前的一个项目中,我总是使用 Arrays.asList,因为它更简单、更清晰的列表初始化。然后我所做的就是将 arrayList 传递给另一个方法,甚至是库。 问题是某些库将 Arrays.ArrayList 视为 ArrayList。因此,当它尝试强制转换为 java.util.ArrayList 时会导致问题

      List<String> arrayList = Arrays.asList(x);
      ArrayList<String> arr = (ArrayList) arrayList; //this will cause error
      
      • 某些映射器(例如:dozer)无法更早地读取 Arrays.asList 的方法签名,因此映射将失败。

      • 我还在某个库上发现了一些案例,当调用某些方法时它甚至会抛出 UnsupportedOperationException,我不知道为什么。

      然后我们重构了所有代码以删除 Arrays.asList 并且不再使用它。

      所以一次性使用,例如仅用于打印,它仍然可以接受,但最好不要使用它来传递价值/长时间使用。

      【讨论】:

        猜你喜欢
        • 2013-12-02
        • 1970-01-01
        • 1970-01-01
        • 2017-08-02
        • 1970-01-01
        • 1970-01-01
        • 2012-03-10
        • 2012-06-07
        • 2011-02-25
        相关资源
        最近更新 更多