我有以下声明:
ArrayList<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("2");
list.add("3");
list.add("4");
现在我的问题是:如果我想从列表中删除“2”,哪种方式更好?
第一种方式:
for(int i = 0; i < list.size(); i++) {
if(list.get(i).equals("2")) {
list.remove(i);
i--;
}
}
第二种方式:
Iterator<String> iterator = list.iterator();
while(iterator.hasNext())
if(iterator.next().equals("2"))
iterator.remove();
两者是否正确安全且效率更高?
是否还有其他方法可以从ArrayList中删除元素而不会出现IndexOutOfBounds
错误?
答案 0 :(得分:5)
实际上,可能更快的是
list.removeAll(Collections.singleton("2"));
在幕后,对于ArrayList
,它基本上会像@Edmund建议的那样创建一个新的数组副本,但是在较低的级别,这可能会带来更高的性能。
正如其他人所提到的,LinkedList
通常可以从大型列表中删除多个元素。
(即使您决定切换到LinkedList
,您仍然可以使用上面的代码,它将等同于使用迭代器方法,对于创建的单例集合以及某些发生额外的方法调用。)
答案 1 :(得分:2)
无论哪种方式都需要为每个删除的元素向下移动元素。如果您的列表非常大,那么创建新列表可能会更快:
ArrayList<String> newList = new ArrayList<String>();
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String val = iterator.next();
if(!val.equals("2"))
newList.add(val);
}
/* Or just return newList, depending on how list is used in subsequent code. */
list.clear();
list.addAll(newList);
您可以考虑使用LinkedList
代替ArrayList
。但基准测试(使用实际用例)是找出效率最高的最佳方法。
答案 2 :(得分:0)
对于单个元素,你的for循环将正常工作(当你移除(不,真的,它会工作正常)。你的迭代方法也是如此。i--
时它会移动 - remove()
自动将元素移到左边)
你只是迭代到ArrayList
的末尾,你不会离开它。在效率方面,它是一种洗涤方式 - 我建议您使用大小为100,000的样本运行时间,看看它是如何运行的。 (无论列表有多大,它仍然是O(N)操作的顺序。)
答案 3 :(得分:-1)
我在一些数据结构书中已经阅读过,迭代器方法更好,
如果list.remove调用循环,evety time它将从0索引开始索引ot项目删除,然后删除元素并移动受影响的元素,它将是o(n2)进程。
但是在iterator.remove的情况下,元素被删除,因为它们被迭代器访问而不必返回列表的开始,因此o(n)进程。