【问题标题】:Regarding immutable List (created by Arrays.asList())关于不可变列表(由 Arrays.asList() 创建)
【发布时间】:2014-10-16 08:04:28
【问题描述】:

当我们使用java.util.Arrays.asList() 从数组创建列表时,列表是不可变的。我只是想知道当List(或SetMap)的基本目的是具有动态大小并能够随意添加、删除元素时,我们为什么要创建一个不可变列表。当我们需要固定大小的数据结构时,我们选择 Array,当我们需要动态数据结构时,我们选择 ListSetMap 等。那么拥有不可变列表的目的是什么?我在执行任务时遇到了这个问题。

【问题讨论】:

  • 可变的意思是不可变的?
  • “在这种情况下”是什么意思?一般来说,我觉得你的问题很难理解。您似乎混淆了数组和列表的概念。
  • 抱歉我的问题有错误。现在更正它们。请检查。

标签: java arrays list collections immutablelist


【解决方案1】:

当我们使用 java.util.Arrays.asList() 从数组创建列表时,列表是可变的。

是和否:可以通过调用修改列表

list.set(index, element);

但列表可能不会在结构上进行修改。这意味着不可能向列表中添加元素或从列表中删除元素。原因很简单,列表仍然是由数组支持的,数组的大小可能不会改变。

当我们需要一个固定大小的可变集合时,我们会选择 Array

这就是这里的关键点:数组不是CollectionArrays.asList 方法主要充当“数组世界”和“集合世界”之间的“桥梁”。

Arrays.asList 方法允许您将数据传递给需要 Collection 的方法:

// A method that expects a collection:
void process(List<String> strings) { ... }

void call()
{
    String array[] = new String[] { "A", "B", "C" };

    // Pass the array (as a list) to the method:
    process(Arrays.asList(array));
}

此应用案例包括从数组创建其他集合。例如,如果您有一个数组并想创建一个包含数组元素的Set,您可以

String array[] = new String[] { "A", "B", "C" };
Set<String> set = new HashSet<String>();
for (String s : array) 
{
    set.add(s);
}

但是使用Arrays.asList 方法可以更方便地做到这一点:

Set<String> set = new HashSet<String>(Arrays.asList(array));

Arrays.asList 方法可以说是 Collection#toArray 方法的对应物,它的工作方向相反(尽管这种方法通常涉及创建和填充一个 new 数组,而 @ 987654333@ 方法只是“包装”一个数组并让它“看起来像”List)。

【讨论】:

  • 我同意 asList 方法充当 Arrays 世界和 Collections 世界之间的桥梁。我也同意有一些方法可以从 Array 创建一个可变列表。但我不清楚为什么一个列表会出现asList 是不可变的吗?使其不可变的主要目的是什么?
  • @Venkat 我已经说过可以修改它的元素,但不能修改列表的大小。其原因是实现了List 接口,以便实际的data 仍然存储在数组中。而在Java中,数组的大小是不能改变的。如果要从数组创建可变列表,可以使用new ArrayList&lt;String&gt;(Arrays.asList(array));。所以他们没有“故意”使列表在结构上不可变。这只是列表由数组支持这一事实的副作用。
  • public E set(int index, E element) { throw new UnsupportedOperationException(); }
【解决方案2】:

是因为AbstractList类中的add(),由Arrays java类(内部使用)下自定义的ArrayList(内部静态类)扩展而来。请注意,这个 add() 方法与 java.util.ArrayList 中定义的不同,而是 java.util.Arrays$ArrayList 中定义的。

数组具有固定大小的属性,由 jvm 本地提供。即使 Arrays.copyOf() 用于增加大小,例如 Arrays.copyOf(arr, 10); //10 is the length,其中原始数组是 arr= int[]{1,2} // size is two。它使用System.arraycopy() 创建总是一个新数组,最终调用本机方法

[static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)]

请注意,上面的列表只有大小限制,如果你真的想让可变列表不可变,请尝试使用Collections.unmodifiableList(mutableList); 不变性不是 jvm 定义的概念,而是开发人员的想法。请参考https://stackoverflow.com/a/42071121/5620851https://stackoverflow.com/a/42138471/5620851

【讨论】:

    【解决方案3】:

    java.util.Arrays.asList() 调用 return new ArrayList&lt;&gt;(a); 但是这个 ArrayList 是一个私有的数组类,它扩展了AbstractList 并覆盖了一些实现。因此,期望java.util.ArrayList 的行为是不公平的。如果您查看java.util.AbstractList,您会发现您可以调用 add(E e) 但不能调用很多其他方法。因此,按照当前的实现,您可以在列表底部添加一个元素,但不能更改列表的现有结构。

    【讨论】:

    • 一直认为返回的ArrayListjava.util.ArrayList。从来不知道这是一个完全不同的课程。
    【解决方案4】:

    如果您拨打System.out.println(Arrays.asList("a", "b").getClass());

    运行时类型为java.util.Arrays$ArrayList

    但是如果你打电话给System.out.println(new ArrayList&lt;&gt;(Arrays.asList("a", "b").getClass()));

    运行时类型是java.util.ArrayList

    也许这种区别会有所帮助。

    【讨论】:

      猜你喜欢
      • 2018-07-18
      • 2017-08-28
      • 2018-11-05
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-31
      相关资源
      最近更新 更多