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 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.
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
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 also cars1.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())
)
);
It can be done simply by using removeAll() method. You have to implement hashcode and equals in Car class. Then you can cars1.removeAll(cars2);
. this statement would leave only c1 in cars1 list.
The recommended solution is to override toString
and hasCode()
methods in the class, Car
and then you can, as already comment below the question, do something like
cars1.removeAll(cars2);
or
cars1.removeIf(cars2::contains);
However, if these two methods are not overridden in the class, Car
, you will have to compare each attribute within the nested loops. This approach is only useful to learn nested loops and is never recommended for production use.
Demo:
import java.util.ArrayList;
import java.util.List;
class Car {
int id;
String name;
@Override
public String toString() {
return "Car [id=" + id + ", name=" + name + "]";
}
}
public class Main {
public static void main(String[] args) {
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);
for (int i = 0; i < cars1.size(); i++) {
Car car1 = cars1.get(i);
for (int j = 0; j < cars2.size(); j++) {
Car car2 = cars2.get(j);
if (car2.id == car1.id && car2.name.equals(car1.name))
cars1.remove(i);
}
}
System.out.println(cars1);
}
}
Output:
[Car [id=1, name=C1]]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.