Stream Filter of 1 list based on another list
It's not clear why you have a List<DataCarName>
in first place instead of a List/Set<String>
.
The predicate you have to provide must check if for the corresponding data car instance, there's its name in the list.
e -> e.getName().contains("BMW")
will only check if the name of the data car contains BMW which is not what you want. Your first attempt then may be
e -> listCarName.contains(e.getName())
but since listCarName
is a List<DataCarName>
and e.getName()
a string (I presume), you'll get an empty list as a result.
The first option you have is to change the predicate so that you get a stream from the list of data car names, map them to their string representation and check that any of these names corresponds to the current data car instance's name you are currently filtering:
List<DataCar> listOutput =
listCar.stream()
.filter(e -> listCarName.stream().map(DataCarName::getName).anyMatch(name -> name.equals(e.getName())))
.collect(Collectors.toList());
Now this is very expensive because you create a stream for each instance in the data car stream pipeline. A better way would be to build a Set<String>
with the cars' name upfront and then simply use contains
as a predicate on this set:
Set<String> carNames =
listCarName.stream()
.map(DataCarName::getName)
.collect(Collectors.toSet());
List<DataCar> listOutput =
listCar.stream()
.filter(e -> carNames.contains(e.getName()))
.collect(Collectors.toList());
in your DataCar type, does getName()
return a String or the DataCarName enum type? If it is the enum, you might follow Alexis C's approach but instead of building a HashSet using Collectors.toSet(), build an EnumSet, which gives O(1) performance. Modifying Alexis' suggestion, the result would look like:
Set<DataCarName> carNames =
listCarName.stream()
.collect(Collectors.toCollection(
()-> EnumSet.noneOf(DataCarName.class)));
List<DataCar> listOutput =
listCar.stream()
.filter(car -> carNames.contains(car.getName()))
.collect(Collectors.toList());