首页 > 解决方案 > 为什么在数组列表数组上使用 Arrays.fill() 时会出现意外行为?

问题描述

我知道混合集合和数组不是一个好主意,但我不明白为什么我会收到这个错误。

说,

ArrayList<Integer>[] x = new ArrayList[2];
Arrays.fill(x, new ArrayList<>());
x[0].add(1);

即使我只是用该值填充索引 0,为什么还要x评估到现在?ArrayList[2] { [1], [1] }

但是,这很好用,

ArrayList<Integer>[] x = new ArrayList[2];
for (int i = 0; i < n; i++) {
    x[i] = new ArrayList<Integer>();
} 
Arrays.fill(x, new ArrayList<>());
x[0].add(1);

x评估为ArrayList[2] { [0], [] }

在第一种Arrays.fill方法中究竟是什么导致了这种异常?

标签: javaarraysarraylistcollections

解决方案


Arrays.fill(x, new ArrayList<>());

这是误导性的,不会做你想做的事。

具体来说,它这样做:

  1. 它创建一个新的 ArrayList 实例。一个例子。就一个。
  2. 然后它会获取您的 ArrayLists 数组,当然,它是一个引用数组。这是一个地址簿,上面有房子的地址,而不是一栋房子。
  3. 然后它用同一个地址填充整个地址簿。仍然只有一所房子。您只制作了一个 ArrayList。

因此,您现在有一个数组,其中数组中的每个“槽”都指向完全相同的数组列表。添加一个整数,x[0]现在x[1].size()也将返回 1。

修复?

嗯,你说的。停止混合这两个概念的这种愚蠢的杂物。更一般地说,你不能fill在这里使用。

更新:但是有setAll

Arrays.setAll(x, idx -> new ArrayList<Integer>());做你想做的事:它为数组中的每个“插槽”调用数组之后的东西。

这是一个简单的规则:

如果您希望 Y 个对象存在,请告诉我如何new Something()运行至少 Y 次。如果你不能提出一个合理的案例,你猜怎么着。你没有 Y 个对象。

在您的基于填充的代码中,我精确计算了 1 次new ....调用,并且没有合理的解释可以解释为什么一次调用会以您想要的方式运行多次(实际上,这就是解释:不是)。因此:是的。该代码不符合您的要求。


推荐阅读