如何根据出现次数过滤条目?

布雷特·瑞安(Brett Ryan)

使用流API,如何在使用groupingBy->counting操作进行收集后包含基于出现次数过滤器的条目的情况下进行过滤?

给定以下内容:

Map<Integer, Long> counts = Stream.of(1, 2, 2, 3, 4, 5, 5)
        .collect(groupingBy(n -> n, counting()));

如何将其过滤为仅包含键25

我可以使用以下内容,但我希望可以继续使用该流,而不需要先进行收集。

Map<Integer, Long> counts = Stream.of(1, 2, 2, 3, 4, 5, 5)
        .collect(groupingBy(n -> n, counting()))
        .entrySet().stream()
        .filter(n -> n.getValue() > 1)
        .collect(toMap(Entry::getKey, Entry::getValue));
霍尔格

无法为依赖已看到的值的操作构建映射或类似的数据结构。例如,distinct这看起来像是操作链中的一个步骤,但是如果没有内部构建地图(或类似地图的结构)就无法工作。

您可以使用以下命令使整个过程看起来像单个流操作

Map<Integer, Long> counts = Stream.of(1, 2, 2, 3, 4, 5, 5)
    .collect(collectingAndThen(groupingBy(n -> n, counting()),
       map -> map.entrySet().stream()
         .filter(n -> n.getValue() > 1)
         .collect(toMap(Entry::getKey, Entry::getValue))
    ));

但这不会改变其工作方式。请记住,必须首先记住每个遇到的值,因为它需要到达流的末尾才能推断出该值不存在其他值。

请注意,有时非流操作可能看起来更简洁:

Map<Integer, Long> counts = Stream.of(1, 2, 2, 3, 4, 5, 5)
    .collect(groupingBy(n -> n, HashMap::new, counting()));
counts.values().removeIf(count -> count < 2);

如果您有兴趣在(可并行处理的)范围内处理项目本身,Stream而又不关心实际出现的次数,则可以使用以下简单解决方案:

ConcurrentHashMap<Integer,Integer> counts=new ConcurrentHashMap<>();
Stream.of(1, 2, 2, 3, 4, 5, 5)
      .filter(i -> counts.merge(i, 1, Integer::sum)==2)
      .forEach(System.out::println);

它允许在遇到第二种项目后立即将后续操作应用于终端操作,而无需处理所有项目或等待流的结尾并与parallel执行和/或短路相协调limitfindAny操作

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章