I have following code-
import java.util.ArrayList;
public class ArrayListExp{
public static void main (String[] args){
ArrayList
The Collection interface now provides a removeIf method that modifies it in place, to which you provide a predicate that returns true
if the element should be removed.
You can thus use a lambda like so:
name.removeIf(name -> name.equals("Meg"));
A method reference can be used as well to be more concise. The following code will also work if there are null
elements.
name.removeIf("Meg"::equals);
If you do not want to modify the old list, you can use Stream and filter to get a List
of all the items that should be retained by negating the condition.
final List<String> filtered = name.stream()
.filter(name -> !"Meg".equals(name))
.collect(Collectors.toList());
If you specifically need an ArrayList
, use Collectors.toCollection
with a constructor reference instead.
final ArrayList<String> filtered = name.stream()
.filter(name -> !"Meg".equals(name))
.collect(Collectors.toCollection(ArrayList::new));
The issue is that the ArrayList is being modified while being iterated over, which changes its size and shifts later elements forward; this is a problem if there are consecutive elements that need to be removed. You need to decrease the index by one each time you remove an element since that index will now refer to the next element.
for (int i = 0; i < name.size(); i++) {
String oldName = name.get(i);
if (oldName.equals("Meg")) {
name.remove(i);
i--;//Important!
}
}
for (int i = name.size() - 1; i >= 0; i--) {
String oldName = name.get(i);
if (oldName.equals("Meg")) {
name.remove(i);
}
}
Generally, using an Iterator
is the most appropriate for this sort of operation, as it supports removing elements while iterating through calling Iterator#remove
. This also modifies the List
in place. For more complex operations, consider using a ListIterator
.
final Iterator<String> it = name.iterator();
while(it.hasNext()){
final String name = it.next();
if(name.equals("Meg")){
it.remove();
}
}
You can use name.removeAll(Arrays.asList("Meg"));
to remove all "Meg"
Your complete code would be
for ( int i = 0; i < name.size(); i++){
String oldName = name.get(i);
if(oldName.equals("Meg"))
{
name.removeAll(Arrays.asList("Meg"));
}
}
You are iterating over the first Meg
, and when that Meg
gets removed, the array values shift over by one.
[Chris, Lois, Meg, Meg, Brain, Peter, Stewie]
0 1 2 3 4 5 6
First Meg
gets removed, and the loop increments i because it finished executing everything inside the for loop, so i
will now be 3 and the array has been modified:
[Chris, Lois, Meg, Brain, Peter, Stewie]
0 1 2 3 4 5
Try iterating backwards.
for ( int i = name.size() - 1; i >= 0; i--){
String oldName = name.get(i);
if(oldName.equals("Meg"))
{
name.remove(i);
}
}
Its because when i=2 and if condition is true then meg is deleted and all the indices are shifted up. hence the next i will point to Brain, not meg.
try this. (decrease i by one when if condition holds true)
for ( int i = 0; i < name.size(); i++){
String oldName = name.get(i);
if(oldName.equals("Meg"))
{
name.remove(i);
i--;
}
}
While removing elements you should not use for loop. It always make problems when implementing some logic. Use reverse for loop for your problem and always try to use for each.
When you remove the first "Meg", the index i=2
. Then it's incremented, but since one of the "Meg" is already removed, now name.get(3)
is "Brain". So you didn't actually check the second "Meg".
To fix the problem. you can decrement the index when you remove an element:
public class ArrayListExp{
public static void main (String[] args){
ArrayList<String> name = new ArrayList<String>();
name.add("Chris");
name.add("Lois");
name.add("Meg");
name.add("Meg");
name.add("Brain");
name.add("Peter");
name.add("Stewie");
System.out.println(name);
for ( int i = 0; i < name.size(); i++){
String oldName = name.get(i);
if(oldName.equals("Meg"))
{
name.remove(i);
i--;
}
}
System.out.println(name);
}
}