Table of Contents
Introduction
In this tutorial, you will learn how to remove element from Arraylist in java while iterating using different implementations provided by Java.
It is necessary to understand the right way to remove items from a List because we might encounter errors in our programs if not done correctly.
For example, If we try to remove an item directly from a List while iterating through the List items, a ConcurrentModificationException is thrown.
The ConcurrentModificationException
is an Exception that occurs when a thread tries to modify another thread that is iterating over the list items.
Since List is an Iterator implementation, the behavior of the iterator is undefined at this point, and if the iterator detects the behavior, it will throw the Exception.
Further reading:
To see this behavior in action, we will create an implementation that throws a ConcurrentModificationException
and then implement different ways to solve the problem.
Create a method named removeItems()
that accepts a list of names and inside it add a for-each
loop that iterates through the list of names to find a name, and if it is found, we use the remove()
method to remove it from the list.
Create a list of names and pass the list to the removeItems()
method, and when you run the program, notice that it throws a ConcurrentModificationException
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.java2code; import java.util.ArrayList; import java.util.List; public class RemoveListItems { public static void main(String[] args){ List<String> list = new ArrayList<>(List.of( "john", "doe", "mary", "public" )); removeItems(list); } public static void removeItems(List<String> names){ for (String name : names) { if (name.equals("john")){ names.remove(name); } } System.out.println(names); } } |
Output:
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1043)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:997)
at com.java2code.RemoveListItems.removeItems(RemoveListItems.java:111)
at com.java2code.RemoveListItems.main(RemoveListItems.java:16)
Create a class named Customer
with field firstName
and lastName
and generate allArgsConstructor
, getter
, setter
, and toString()
methods. We will use this class to create our custom list of objects and try to remove an object from a list based on a condition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public class Customer{ private String firstName; private String lastName; public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getLastName() { return lastName; } public String getFirstName() { return firstName; } @Override public String toString() { return "Customer{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + '}'; } } |
Using Collection’s removeIf()
method
The removeIf()
is a method from the Collection interface that accepts a Predicate which is simply a functional interface that accepts one value and returns a boolean.
This method removes all the elements that evaluate the Predicate
to true, and any runtime exceptions that occur during the iteration are passed to the caller.
The items in the list are traversed using iterator()
, and any matching item is removed using the remove()
method. If the iterator implementation does not support remove operation, it throws UnsurpportedOperationException
on the first matching element.
If any elements are removed, the method returns true, and if the provided filter is null, it throws a NullPointerException.
Create a list of customer objects and use the equals()
method in the removeIf()
method to remove a specified name if found in the List.
Log the modified list to the console and observe that the customer with the given name was removed from the list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.java2code; import java.util.ArrayList; import java.util.List; public class RemoveListItems { public static void main(String[] args){ List<Customer> customers = new ArrayList<>( List.of( new Customer("john","doe"), new Customer("mary","public"), new Customer("peter","parker"), new Customer("alex","anderson") ) ); Predicate<Customer> filterName = customer -> customer.getFirstName().equals("john"); customers.removeIf(filterName); customers.forEach(System.out::println); } } |
Output:
Customer{firstName=’peter’, lastName=’parker’}
Customer{firstName=’alex’, lastName=’anderson’}
Using ListIterator
class
ListIterator
is an Iterator
implementation that allows us to modify a list during the iteration and traversed in both forward and previous directions.
You can call next()
or previous()
when traversing the list, and the remove()
method is implemented to operate on the last element returned by a call to previous or next.
If previous or next has not been called or you made a call to add or remove after the last call to previous or next, the method throws an IllegalStateException
.
Create a list of integers and use the hasNext()
method to iterate through the list and add an if statement that checks for an item using a call to next()
.
Remove the item from the list if it is found and log the modified list to the console to verify that the item was removed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.java2code; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; public class RemoveListItems { public static void main(String[] args) { List<Integer> integers = new ArrayList<>( List.of( 1,2,3,4,5,6,7,8 ) ); ListIterator listIterator = integers.listIterator(); while (listIterator.hasNext()){ if (listIterator.next().equals(5)){ listIterator.remove(); } } integers.forEach(System.out::println); } } |
Output:
2
3
4
6
7
8
Using removeAll()
method
The removeAll()
is a method of the Collection interface that accepts a collection of elements and removes all the elements that are contained in the collection.
The method returns true if the collection changes as a result of the call.
The method throws UnsupportedOperationException
if the method is not supported by this
collection, a ClassCastException
if the specified collection has a type incompatible with it, and a NullPointerException if the provided collection is null or has a null element or the specified collection, does not support null elements.
Create a list of elements and traverse through the list using the for-each method and add the elements you want to remove to a new List.
Call the modified list removeAll()
method and pass the new list we have just created and observe that it removes the items in the new list from the original list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.java2code; import java.util.ArrayList; import java.util.List; public class RemoveListItems { public static void main(String[] args){ List<Character> characters = new ArrayList<>( List.of( 'A','B','C','D','E','F' ) ); List<Character> charactersToRemove = new ArrayList<>(); for (Character character : characters) { if (character.equals('D')){ charactersToRemove.add(character); } } characters.removeAll(charactersToRemove); characters.forEach(System.out::println); } } |
Output:
B
C
E
F
Using Java 8 Stream
to filter List items
Create a list of customer objects and call the stream()
method from the list, which will return a Stream
of the list items.
The Java 8 Stream will allow us to perform aggregate operations on the stream to get our desired output.
The stream()
method will be followed by a call to the filter() method that accepts a Predicate which is a functional interface that accepts a single input and returns a boolean.
The filter method will remove the customer object that we specify and return a list with the remaining customer objects using the Collectors.toList()
method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com.java2code; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class RemoveListItems { public static void main(String[] args){ List<Customer> customers = new ArrayList<>( List.of( new Customer("john","doe"), new Customer("mary","public"), new Customer("peter","parker"), new Customer("alex","anderson") ) ); List<Customer> filteredList = customers.stream() .filter(customer -> !customer.getFirstName().equals("peter")) .collect(Collectors.toList()); filteredList.forEach(System.out::println); } } |
Output:
Customer{firstName=’mary’, lastName=’public’}
Customer{firstName=’alex’, lastName=’anderson’}
Conclusion
In this tutorial, you have learned what is ConcurrentModificationException
and how it comes about when removing items while traversing through a list. You have also learned how to avoid this Exception by using the removeIf()
, removeAll()
, ListIterator
class, and Java 8 Stream.