我常常需要迭代一个ArrayList
,并希望根据任何条件从中创建一个子集。
从性能的角度来看:对于我想要删除的元素使用迭代器和iterator.remove()
是否更好,或者我应该将这些元素添加到新列表中?
for (Iterator<Object> it = list.iterator(); it.hasNext(); ) {
Object item = it.next();
if (!conditionMatches(item)) {
it.remove();
}
}
或
List<Object> newList = new ArrayList<>();
for (Object item : list) {
it (contitionMatches(item)) {
newList.add(item);
}
}
答案 0 :(得分:4)
选项1 不适用于只读列表,例如Arrays.asList
返回的列表。
此外,remove
中的ArrayList
是一个重要的代价,因为必须复制大部分支持数组才能列出该列表。
选项2 适用于所有列表。
这也是我们鼓励与流一起使用的模式:
List<String> l = Arrays.asList("A","B","C");
List<String> filtered = l.stream()
.filter(s -> s.equals("A"))
.collect(Collectors.toList());
恕我直言 - 使用这一个。选项1中的节省是虚幻的。
答案 1 :(得分:2)
时间复杂度:选项2最好
空间复杂性:选项1最好
ArrayList remove是O(n),而add是O(1),但是,你必须为新列表分配新的内存。
答案 2 :(得分:2)
如果您只需删除一个元素,则无论哪种方式都可以。如果要删除某个点之后的所有元素,可以采用任意一种方式(向后迭代以进行删除)。然而,一般而言,复制方法可能花费更少的时间。如果您希望修改列表,可以考虑removeIf
。尽管文档没有说明它是如何工作的,但它很可能会跟踪“到”和“从”索引,在一次传递中将所有元素向下移动。复制或修改方法是否最合适肯定取决于您使用列表的方式,(如果我对removeIf
的猜测是正确的话)也可能取决于删除了哪些元素。
答案 3 :(得分:0)
如果你想从列表中删除值,你需要从头到尾进行,如下所示:
for (int i=list.size()-1; i>=0; i--) {
if (contitionMatches(list.get(i))) {
list.remove(i);
}
}
答案 4 :(得分:0)
第二个选项更快,因为当移除当前位置的元素时,它不涉及移动所有后续元素。
当谈到更大的ArrayList
时,我甚至敢说第一种选择是反模式。