1

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?

1 Answer 1

1

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() ); 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.