java - 为什么在数组列表数组上使用 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
方法中究竟是什么导致了这种异常?
解决方案
Arrays.fill(x, new ArrayList<>());
这是误导性的,不会做你想做的事。
具体来说,它这样做:
- 它创建一个新的 ArrayList 实例。一个例子。就一个。
- 然后它会获取您的 ArrayLists 数组,当然,它是一个引用数组。这是一个地址簿,上面有房子的地址,而不是一栋房子。
- 然后它用同一个地址填充整个地址簿。仍然只有一所房子。您只制作了一个 ArrayList。
因此,您现在有一个数组,其中数组中的每个“槽”都指向完全相同的数组列表。添加一个整数,x[0]
现在x[1].size()
也将返回 1。
修复?
嗯,你说的。停止混合这两个概念的这种愚蠢的杂物。更一般地说,你不能fill
在这里使用。
更新:但是有setAll
:
Arrays.setAll(x, idx -> new ArrayList<Integer>());
做你想做的事:它为数组中的每个“插槽”调用数组之后的东西。
这是一个简单的规则:
如果您希望 Y 个对象存在,请告诉我如何new Something()
运行至少 Y 次。如果你不能提出一个合理的案例,你猜怎么着。你没有 Y 个对象。
在您的基于填充的代码中,我精确计算了 1 次new ....
调用,并且没有合理的解释可以解释为什么一次调用会以您想要的方式运行多次(实际上,这就是解释:不是)。因此:是的。该代码不符合您的要求。
推荐阅读
- python - Discord 同步处理命令并立即回复每个人。(使用不和谐.py)
- r - R,将数据框中的字符串更改为二进制值
- ruby-on-rails - 调试时传递参数
- json - BigDecimal 到 Double 以添加到 JSON 对象
- javascript - Javascript在for循环中使用值作为对象键?
- android - 在列的可用空间中拉伸小部件
- vue.js - v-on 处理程序中的 Vue 错误:“TypeError:无法读取 null 的属性”
- javascript - 如何使用 React 按钮组件向下滚动页面?
- python - 循环 json 数据并合并 df 数据
- google-cloud-platform - 如何使用 Colab 在 Google Drive 和 Google Cloud Storage 之间复制大文件