I want to know if there is an impementation of "plucking" elements from a Collection implementation based from a given Predicate, that is to remove said elements after retrieving. To visualize what I mean, consider this use case:
Set<Parent> parentSet = parentDao.getParents();
Set<Long> parentIdSet = parentSet.stream().map(Parent::getId).collect(Collectors.toSet())
Set<Child> childrenSet = childDao.getChildByParentIds(parentIdSet);
for (Parent parent : parentSet) {
Set<Child> childrenOfThisParent = childrenSet
.stream()
.pluck((Child c) -> Objects.equals(parent.getId(), c.getParentId()))
.collect(Collectors.toSet());
parent.setChildren(childrenOfThisParent);
}
// At this line, childSet should be empty.
assert(childrenSet.isEmpty());
What I want is every iteration, after Set<Child> was filtered by its parentId and initialized to childrenOfThisParent, I want them to be removed from the childSet and get the size() of childSet reduced. By effect, the searching from childSet should be faster the next iteration. Although at this point, I have to benchmark to know if the faster search time will be significant.
Streams just don't support "in place" operations like modifying an existing collection. If you want to do this with streams, you would need to produce new collections. You can use the
partitioningBycollector to separate the children set into "children of this parent" and "not children of this parent". Both of these are new collections, stored in a newMap.This allocates a whole lot of new collections, so probably isn't worth it. You can consider doing the whole operation of "grouping children into their parents" in one stream, using
groupingBy: