Java 8 收集深度属性上的groupBy private Map populateZuloSquare(列出正方形){ if(squares==null | | squares.isEmpty()){ 返回空映射(); } Map res=新的HashMap(); squares.stream() .过滤器(方形->{ if(square.getZuloCodes().isEmpty()){ LOG(“忽略{}”,square.id); 返回false; } 返回true; }) .forEach(方形->{ square.getZuloCodes() .forEach(代码->{ res.putIfAbsent(代码,new HashSet()); res.get(代码)。add(正方形); })); }); 返回集合。不可修改映射(res); }

Java 8 收集深度属性上的groupBy private Map populateZuloSquare(列出正方形){ if(squares==null | | squares.isEmpty()){ 返回空映射(); } Map res=新的HashMap(); squares.stream() .过滤器(方形->{ if(square.getZuloCodes().isEmpty()){ LOG(“忽略{}”,square.id); 返回false; } 返回true; }) .forEach(方形->{ square.getZuloCodes() .forEach(代码->{ res.putIfAbsent(代码,new HashSet()); res.get(代码)。add(正方形); })); }); 返回集合。不可修改映射(res); },java-8,java-stream,collectors,Java 8,Java Stream,Collectors,上面的代码接收一个方块列表,这些方块中可能包含ZuloCodes。输出应该是一个不可变的Map zuloCode,并为所有带有该UniquePrefix的方块赋值。 如您所见,我无法找到删除辅助集合res并使代码易于阅读的方法,是否有方法将该集合分解为[zuloCode,square],然后再分解为collect.groupBy?另外,如果过滤器内部无法读取,您将如何处理它?如何处理。您可以使用mapmerge操作来完成此操作。我已经更新了过滤器并简化了它 private Map<Stri

上面的代码接收一个方块列表,这些方块中可能包含ZuloCodes。输出应该是一个不可变的Map zuloCode,并为所有带有该UniquePrefix的方块赋值。
如您所见,我无法找到删除辅助集合res并使代码易于阅读的方法,是否有方法将该集合分解为[zuloCode,square],然后再分解为collect.groupBy?另外,如果过滤器内部无法读取,您将如何处理它?

如何处理。您可以使用
map
merge
操作来完成此操作。我已经更新了过滤器并简化了它

private Map<String, Set<Square>> populateZuloSquare(List<Square> squares) {
    if (squares == null || squares.isEmpty()) {
        return emptyMap();
    }

    Map<String, Set<Square>> res = new HashMap<>();

    squares.stream()
        .filter(square -> {
            if (square.getZuloCodes().isEmpty()) {
                LOG("Ignored {}", square.id);
                return false;
            }
            return true;
        })
        .forEach(square -> {
          square.getZuloCodes()
            .forEach(code -> {
                res.putIfAbsent(code, new HashSet<>());
                res.get(code).add(square);
            }));
        });

    return Collections.unmodifiableMap(res);
}
squares.stream().filter(s->!s.getZuloCodes().isEmpty())
.forEach(s->s.getZuloCodes().stream().forEach(z->res.merge(z,新哈希集(Arrays.asList)),
(s1,s2)->Stream.of(s1,s2).flatMap(Collection::Stream).collect(Collectors.toSet());

标准方法是在使用
groupingBy
进行收集之前使用
flatMap
,但由于每个元素都需要原始的
正方形
,因此需要映射到同时包含
正方形
实例和zulo代码
字符串
的对象

由于Java中还没有标准的对或元组类型,一种解决方法是使用
Map.Entry
实例,如下所示

squares.stream().filter(s -> !s.getZuloCodes().isEmpty())
    .forEach(s -> s.getZuloCodes().stream().forEach(z -> res.merge(z, new HashSet<>(Arrays.asList(s)),
        (s1, s2) -> Stream.of(s1, s2).flatMap(Collection::stream).collect(Collectors.toSet()))));
private Map populateZuloSquare0(列表正方形){
if(squares==null | | squares.isEmpty()){
返回空映射();
}
返回正方形。stream()
.filter(square->logMismatch(square,!square.getZuloCodes().isEmpty())
.flatMap(square->square.getZuloCodes().stream())
.map(代码->新建AbstractMap.SimpleEntry(代码,正方形)))
收集,收集收集,然后收集(
Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,Collectors.toSet()),
集合::不可修改映射);
}
私有静态布尔逻辑不匹配(平方、布尔匹配){
if(!match)LOG(“忽略{}”,square.id);
复赛;
}
另一种方法是使用自定义收集器,该收集器将迭代键:

private Map<String, Set<Square>> populateZuloSquare0(List<Square> squares) {
    if (squares == null || squares.isEmpty()) {
        return emptyMap();
    }
    return squares.stream()
        .filter(square -> logMismatch(square, !square.getZuloCodes().isEmpty()))
        .flatMap(square -> square.getZuloCodes().stream()
            .map(code -> new AbstractMap.SimpleEntry<>(code, square)))
        .collect(Collectors.collectingAndThen(
            Collectors.groupingBy(Map.Entry::getKey,
                Collectors.mapping(Map.Entry::getValue, Collectors.toSet())),
            Collections::unmodifiableMap));
}
private static boolean logMismatch(Square square, boolean match) {
    if(!match) LOG("Ignored {}", square.id);
    return match;
}
private Map populateZuloSquare(列出正方形){
if(squares==null | | squares.isEmpty()){
返回空映射();
}
返回正方形。stream()
.filter(square->logMismatch(square,!square.getZuloCodes().isEmpty())
收集(
HashMap::新建,
(m,square)->square.getZuloCodes()
.forEach(code->m.computeIfAbsent(code,x->new HashSet()).add(square)),
(m1,m2)->{
如果(m1.isEmpty())返回m2;
m2.forEach((键,集合)->
m1.merge(key,set,(s1,s2)->{s1.addAll(s2);返回s1;});
返回m1;
},
集合::不可修改映射)
);
}
请注意,此自定义收集器可以看作是以下循环代码的一个支持并行的变体:

private Map<String, Set<Square>> populateZuloSquare(List<Square> squares) {
    if (squares == null || squares.isEmpty()) {
        return emptyMap();
    }
    return squares.stream()
        .filter(square -> logMismatch(square, !square.getZuloCodes().isEmpty()))
        .collect(Collector.of(
            HashMap<String, Set<Square>>::new,
            (m,square) -> square.getZuloCodes()
                .forEach(code -> m.computeIfAbsent(code, x -> new HashSet<>()).add(square)),
            (m1,m2) -> {
                if(m1.isEmpty()) return m2;
                m2.forEach((key,set) ->
                    m1.merge(key, set, (s1,s2) -> { s1.addAll(s2); return s1; }));
                return m1;
            },
            Collections::unmodifiableMap)
        );
}
private Map populateZuloSquare(列出正方形){
if(squares==null | | squares.isEmpty()){
返回空映射();
}
Map res=新的HashMap();
正方形。forEach(正方形->{
if(square.getZuloCodes().isEmpty())LOG(“忽略{}”,square.id);
else square.getZuloCodes().forEach(
code->res.computeifassent(code,x->newhashset()).add(square));
});
返回集合。不可修改映射(res);
}

现在看起来可能没那么糟糕,当你不需要代码来实现并行功能时…

进行地图合并而不是putIfAbsent看起来效率更低,而且更不可读,还保留了辅助地图。你能给我们看一下你的基准测试结果吗,或者给我们指出任何说明这一点的站点。我从未见过文档中提到的这种事情。从字面上看,这种方法更具声明性和不可更改性——没有基准,但让我们假设100个正方形?您的场景将创建1000个映射、100个条目、100个集合和100个数组.asList,并在最佳和最坏情况下合并它们。(你可以考虑单列表而不是ASLIST)-在我的:最坏的情况下没有重复,我将创建1个地图,100个条目,100个集合,并做100个设置。100%重复的最佳情况我将创建一个地图,一组,并执行100次添加。。。我相信我的平均执行速度更快,因为我的数据集很少出现最坏的情况,而你的数据集可能更具声明性,我可能错了,尽管这只是一种粗略的感觉对不起,拼写错误1000应该读100。。。从1000个示例开始,但当我用完字符时,每个字符都删除了0个,我想我错过了一个
private Map<String, Set<Square>> populateZuloSquare(List<Square> squares) {
    if (squares == null || squares.isEmpty()) {
        return emptyMap();
    }
    Map<String, Set<Square>> res = new HashMap<>();
    squares.forEach(square -> {
        if(square.getZuloCodes().isEmpty()) LOG("Ignored {}", square.id);
        else square.getZuloCodes().forEach(
            code -> res.computeIfAbsent(code, x -> new HashSet<>()).add(square));
    });
    return Collections.unmodifiableMap(res);
}