Remove list from list Java

This post will discuss how to remove elements from a mutable list in Java that satisfies the given predicate.

Fail Fast Iterator vs Fail Safe Iterator in Java


It is not allowed to modify a list [add elements to it, remove elements from it, etc.] while iterating over it; otherwise, a ConcurrentModificationException will be thrown to avoid non-deterministic behavior. We can use any of the following methods to efficiently remove elements from the list that matches the given predicate without throwing ConcurrentModificationException.

1. Using an iterator

The Iterator interface provides the remove[] method, which removes the last element returned by the iterator. The idea is to get an iterator to the given list and use the remove[] method to remove elements on which the predicate is satisfied.

1
2
3
4
5
6
7
8
9
10
11
12
13
// Generic method to remove elements from a list in Java
public static void remove[List list, Predicate predicate]
{
Iterator itr = list.iterator[];
while [itr.hasNext[]]
{
T t = itr.next[];
if [predicate.test[t]] {
itr.remove[];
}
}
}


Please note that the iterator will throw a ConcurrentModificationException if the list is modified after it is created except through the iterators own remove method.

2. Using removeAll[] method

We can maintain a separate collection containing elements from the original list that matches the given predicate. Then we can use the removeAll[] method provided by the List interface to remove elements of that collection from the original list.

1
2
3
4
5
6
7
8
9
10
11
12
// Generic method to remove elements from a list in Java
public static void remove[List list, Predicate predicate]
{
Collection collection = new ArrayList[];
for [T t: list]
{
if [predicate.test[t]] {
collection.add[t];
}
}
list.removeAll[collection];
}

3. Using Java 8

In Java 8, we can use Stream to remove elements from a list by filtering the stream easily.

⮚ Using Collectors

The idea is to convert the specified list to a sequential Stream, filter the stream and accumulate the elements that match the given predicate into a new list using a Collector.

1
2
3
4
5
6
7
// Generic method to remove elements from a list in Java 8
public static List remove[List list, Predicate predicate]
{
return list.stream[]
.filter[x -> !predicate.test[x]]
.collect[Collectors.toList[]];
}


Please note that this method will return a new list instance, and the original list remains unchanged. Also, it doesnt guarantee the type of the List returned, so we can use Collectors.toCollection[] to specify the desired list type:

1
2
3
4
5
6
7
// Generic method to remove elements from a list in Java 8
public static List remove[List list, Predicate predicate]
{
return list.stream[]
.filter[x -> !predicate.test[x]]
.collect[Collectors.toCollection[ArrayList::new]];
}

⮚ Using forEach[] with List.add[]

This is similar to the earlier approach, where we maintain a separate collection containing the elements from the original list that matches the given predicate and using the List.removeAll[] method to remove those elements from the original list.

1
2
3
4
5
6
7
8
9
10
// Generic method to remove elements from a list in Java 8
public static void remove[List list, Predicate predicate]
{
List newList = new ArrayList[];
list.stream[]
.filter[predicate::test]
.forEach[newList::add];
list.removeAll[newList];
}


We can also perform filtering inside the forEach[] method, as shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Generic method to remove elements from a list in Java 8
public static void remove[List list, Predicate predicate]
{
List newList = new ArrayList[];
list.stream[]
.forEach[x -> {
if [predicate.test[x]] {
newList.add[x];
}
}];
list.removeAll[newList];
}

⮚ Using forEach[] with List.remove[]

Since we cant modify a list while iterating over it, we can create a duplicate list and remove elements that satisfy the predicate from the original list by iterating over the duplicate list.

The following code uses Java 8 Stream to do the filtering, but we can also use an iterator or a for-each loop.

1
2
3
4
5
6
7
8
// Generic method to remove elements from a list in Java 8
public static void remove[List list, Predicate predicate]
{
List duplicate = new ArrayList[list];
duplicate.stream[]
.filter[predicate::test]
.forEach[list::remove];
}


We can also perform filtering inside the forEach[] method, as shown below:

1
2
3
4
5
6
7
8
9
10
11
// Generic method to remove elements from a list in Java 8
public static void remove[List list, Predicate predicate]
{
List duplicate = new ArrayList[list];
duplicate.stream[]
.forEach[x -> {
if [predicate.test[x]] {
list.remove[x];
}
}];
}

⮚ Using removeIf[]

The List interface provides the removeIf[] method that removes all the list elements that satisfy the given predicate. This is the simplest approach among all approaches discussed above and uses Iterator.remove[] behind the scenes.

1
2
3
4
// Generic method to remove elements from a list in Java 8
public static void remove[List list, Predicate predicate] {
list.removeIf[x -> predicate.test[x]];
}

Thats all about removing elements from a list that satisfies a given predicate in Java.


Suggested Read:

Remove elements from a list while iterating over it in Java

Video liên quan

Chủ Đề