Reputation: 271
Is it possible to go back to the parent-object after applying flatmap()
operation, and accumulate parent-objects into a set?
I have an UnifiedOfferEntity
with set of other entity objects as a field:
public static class UnifiedOfferEntity {
private Set<ContractDetailsEntity> contractDetails;
// getters, etc.
}
I would like to filter through fields of the parent-object (UnifiedOfferEntity
) like this:
offersFromDB.stream()
.filter(offer -> CollectionUtils.containsAny(preferences.getOwnedSkills(), offer.getSkills())
&& CollectionUtils.containsAny(preferences.getOwnedSeniority(), offer.getSeniority()))
And then I would like to examine the nested collection, filter through child-objects (ContractDetailsEntity
):
.flatMap(offer -> offer.getContractDetails().stream()
.filter(cd -> cd.getSalaryFrom() >= preferences.getSalaryMin())
And finally, I need to move back to the parent-object and collect its instances into a Set after these filters.
I was trying with this:
List<UnifiedOfferEntity> offersFromDB = // initializing somehow
Set<UnifiedOfferEntity> result = offersFromDB.stream()
.filter(offer -> CollectionUtils.containsAny(preferences.getOwnedSkills(), offer.getSkills())
&& CollectionUtils.containsAny(preferences.getOwnedSeniority(), offer.getSeniority()))
.flatMap(offer -> offer.getContractDetails().stream()
.filter(cd -> cd.getSalaryFrom() >= preferences.getSalaryMin() &&
cd.getSalaryTo() <= preferences.getSalaryMax() &&
tocPreferences.contains(cd.getTypeOfContract())))
.collect(Collectors.toSet())
But it creates a Set
of ContractDetailsEntity
, not UnifiedOfferEntity
. How can I fix this?
Upvotes: 1
Views: 785
Reputation: 28988
You can perform filtering based on the contents of the nested collection (a set of ContractDetailsEntity
) and then accumulate enclosing objects (ContractDetails
) for which provided Predicate
has been evaluated to true
by using built-in collector filtering()
, which expects a predicate and a downstream collector.
If I understood correctly, you need only instances of UnifiedOfferEntity
which have all the ContractDetailsEntity
that match a particular Predicate. To filter such offers, you can generate a stream of contractDetails and apply allMatch()
with all the conditions you've listed (in case if it's sufficient when only one instance of ContractDetailsEntity
meets the conditions - apply anyMatch()
instead).
That's how it might look like:
List<UnifiedOfferEntity> offersFromDB = // initializing offersFromDB
Set<UnifiedOfferEntity> result = offersFromDB.stream()
.filter(offer -> CollectionUtils.containsAny(preferences.getOwnedSkills(), offer.getSkills())
&& CollectionUtils.containsAny(preferences.getOwnedSeniority(), offer.getSeniority()))
.collect(Collectors.filtering(
offer -> offer.getContractDetails().stream().allMatch(cd -> // a Predicate for evalueating ContractDetails goes here
cd.getSalaryFrom() >= preferences.getSalaryMin()
&& cd.getSalaryTo() <= preferences.getSalaryMax()
&& tocPreferences.contains(cd.getTypeOfContract())),
Collectors.toSet()
);
Upvotes: 1