简体   繁体   English

从ArrayList中删除元素的哪种方式更有效?

[英]Which way of removing elements from an ArrayList is more efficient?

I have the following declarations: 我有以下声明:

ArrayList<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("2");
list.add("3");
list.add("4");

Now my question is: if I want to remove the "2"s from the list, which way is better? 现在我的问题是:如果我想从列表中删除“2”,哪种方式更好?

first way: 第一种方式:

for(int i = 0; i < list.size(); i++) {
    if(list.get(i).equals("2")) {
        list.remove(i);
        i--;
    }
}

second way: 第二种方式:

Iterator<String> iterator = list.iterator();
    while(iterator.hasNext())
        if(iterator.next().equals("2"))
            iterator.remove();

Are both safed properly and which is more efficient? 两者都安全正确,哪个更有效?

Are there any other methods to remove elements from an ArrayList without getting IndexOutOfBounds errors? 是否还有其他方法可以从ArrayList中删除元素而不会导致IndexOutOfBounds错误?

Actually, what might be faster is 实际上,可能更快的是

list.removeAll(Collections.singleton("2"));

Behind the scenes, for an ArrayList , it does basically create a new copy of the array like @Edmund suggests, but at a lower level, which may lead to higher performance. 在幕后,对于ArrayList ,它基本上创建了一个新的数组副本,如@Edmund建议,但在较低的级别,这可能会带来更高的性能。

Still, as others have mentioned, a LinkedList generally has better performance for removing multiple elements from a large list. 尽管如此,正如其他人所提到的, LinkedList通常具有更好的性能,可以从大型列表中删除多个元素。

(Even if you do decide to switch to a LinkedList you can still use the above code, it will be equivalent to using the iterator method with a little bit of overhead for the singleton collection that's created and for some extra method calls that happen.) (即使您决定切换到LinkedList您仍然可以使用上面的代码,它将等同于使用迭代器方法,对于创建的单例集合以及发生的一些额外方法调用会产生一些开销。)

Either way is going to need to shift elements down for each element removed. 无论哪种方式都需要为每个删除的元素向下移动元素。 If your list is really big, it could well be faster to create a new list: 如果您的列表非常大,那么创建新列表可能会更快:

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);

You could think about using LinkedList instead of ArrayList . 您可以考虑使用LinkedList而不是ArrayList But benchmarking (with realistic use cases) is the best way to find out what's most efficient. 但基准测试(使用实际用例)是找出效率最高的最佳方法。

For individual elements, your for-loop will work fine (well, it will when you remove i-- - the remove() automatically shifts elements over to the left) (No really, it will work fine). 对于单个元素,你的for循环将正常工作(好吧,当你删除i--它会 - remove()自动将元素移到左边) (不,它会工作正常)。 So will your iteration method. 你的迭代方法也是如此。

You're only iterating to the end of the ArrayList , and you won't step off of it. 你只是迭代到ArrayList的末尾,你不会离开它。 In terms of efficiency, it's a wash - I would recommend you sample runtimes with sizes of 100,000 and see how it goes. 在效率方面,它是一种洗涤方式 - 我建议您使用大小为100,000的样本运行时间,看看它是如何运行的。 (It's still on the order of O(N) operations, no matter how large the list is.) (无论列表有多大,它仍然是O(N)操作的顺序。)

I have read it in some data structure book, that iterator approach is better, 我在一些数据结构书中读过它,迭代器方法更好,

in case of list.remove call under loop, evety time it will start from 0 index to index ot item to remove, then remove element and shift affected elements, it will be o(n2) process. 如果list.remove调用循环,evety time它将从0索引开始索引ot项目删除,然后删除元素并移动受影响的元素,它将是o(n2)进程。

but in case of iterator.remove, element are removed as they are accessed by iterator without having to go back at beggining of list, thus o(n) process. 但是在iterator.remove的情况下,元素被删除,因为它们被迭代器访问而不必返回列表的开始,因此o(n)进程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM