Reputation: 51
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?
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?
Upvotes: 5
Views: 3639
Reputation: 23455
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.
Still, as others have mentioned, a LinkedList
generally has better performance for removing multiple elements from a large list.
(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.)
Upvotes: 5
Reputation: 106390
For individual elements, your for-loop will work fine (well, it will when you remove (No really, it will work fine). So will your iteration method.i--
- the remove()
automatically shifts elements over to the left)
You're only iterating to the end of the ArrayList
, and you won't step off of it. In terms of efficiency, it's a wash - I would recommend you sample runtimes with sizes of 100,000 and see how it goes. (It's still on the order of O(N) operations, no matter how large the list is.)
Upvotes: 0
Reputation: 3535
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.
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.
Upvotes: -1
Reputation: 10809
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
. But benchmarking (with realistic use cases) is the best way to find out what's most efficient.
Upvotes: 2