I didn't find any thread here on this Question. I am trying to Remove elements (Cars in my case) of one list (cars1) if they present in another list (cars2) using Java stream.
I tried using removeIf but then it felt like it works more appropriately with List of Strings, etc. instead of objects.
Imagine the sample codes below:
Car c1 = new Car();
c1.id = 1;
c1.name = "C1";
Car c2 = new Car();
c2.id = 2;
c2.name = "C2";
List<Car> cars1 = new ArrayList<Car>();
cars1.add(c1);
cars1.add(c2);
List<Car> cars2 = new ArrayList<Car>();
cars2.add(c2);
// TODO : Remove all the cars from cars1 list that are in cars2 list using java streams
How to remove all the cars from cars1 list that are present in cars2 list using java streams?
If methods hashCode
and equals
are properly implemented in class Car
, the stream-based solutions may look as follows:
// Predicate.not added in Java 11
List<Car> notJava11 = cars1.stream()
.filter(Predicate.not(cars2::contains))
.collect(Collectors.toList());
List<Car> notIn2 = cars1.stream()
.filter(car -> !cars2.contains(car))
.collect(Collectors.toList());
forEach
for cars2
(affecting cars1
):cars2.forEach(cars1::remove);
// no need to call cars2.stream().forEach(cars1::remove);
Here the first occurrence of Car instance is removed in cars1
removeIf
should work alsocars1.removeIf(cars2::contains);
If you due to some reason equals
/hashCode
are not overridden in class Car
, the following solution may be offered:
List<Car> notIn2 = cars1
.stream()
.filter(c1 -> cars2
.stream()
.noneMatch(c2 ->
c1.getId() == c2.getId()
&& Objects.equals(c1.getName(), c2.getName())
)
)
.collect(Collectors.toList());
removeIf
:cars1.removeIf(c1 -> cars2
.stream()
.anyMatch(c2 -> c1.getId() == c2.getId()
&& Objects.equals(c1.getName(), c2.getName())
)
);