如何用partitioningBy简化Java List分区,得到与原代码一致的Map结果?
Great question! The problem with your initial partitioningBy approach is that it’s meant to split individual elements into two groups using a predicate— but your two target results are distinct collection-level operations:
UnionMandatoryis the union of allisRequired=trueattributes across every validapplicableAttributeslistIntersectedAllis the intersection of all validapplicableAttributeslists themselves
Here’s a concise stream-based implementation that aligns exactly with your original forEach logic, without sacrificing readability:
// First, collect all non-null, non-empty applicable attribute lists to avoid redundant processing List<List<Attribute>> validApplicableLists = givenNames.stream() .map(this::getAllApplicableAttributes) .filter(Objects::nonNull) .filter(list -> !list.isEmpty()) .collect(Collectors.toList()); // Calculate UnionMandatory: union of all required attributes across all valid lists Set<Attribute> unionMandatory = validApplicableLists.stream() .flatMap(List::stream) .filter(Attribute::getIsRequired) .collect(Collectors.toSet()); // Calculate IntersectedAll: intersection of all valid applicable attribute lists Set<Attribute> intersectedAll = validApplicableLists.stream() .map(HashSet::new) // Convert each list to a mutable Set for retainAll .reduce((currentIntersection, nextSet) -> { currentIntersection.retainAll(nextSet); return currentIntersection; }) .orElseGet(HashSet::new); // Return empty set if there are no valid lists // Assemble the final map Map<String, Set<Attribute>> applicableAttributeMap = new HashMap<>(); applicableAttributeMap.put("UnionMandatory", unionMandatory); applicableAttributeMap.put("IntersectedAll", intersectedAll);
Key Details & Explanations:
- Redundant Processing Avoidance: We first collect all valid
applicableAttributeslists (non-null, non-empty) into aList. This means we only processgivenNamesonce to filter out invalid entries, instead of doing it twice for each result. - UnionMandatory Calculation: Using
flatMapwe flatten all valid lists into a single stream of attributes, filter for required ones, and collect to aSet(which automatically handles duplicates, giving us the union). - IntersectedAll Calculation:
- We convert each valid list to a
HashSet(mutable, efficient forretainAlloperations) reduceis perfect here: it starts with the first set, then iteratively appliesretainAllwith each subsequent set to build up the intersectionorElseGetensures we return an empty set if there are no valid lists (matching your original logic whereintersectedAttributesstays empty)
- We convert each valid list to a
Why Your partitioningBy Attempt Didn’t Work
Collectors.partitioningBy splits individual elements into two groups based on a predicate (e.g., all required attributes vs non-required). But your IntersectedAll requires comparing entire lists of attributes across givenName entries, not grouping individual attributes. This is a collection-level operation, not an element-level grouping— so partitioningBy isn’t the right tool for the job.
内容的提问来源于stack exchange,提问作者AshwinK

