Java分组方式:通过单个Stream获得两个(或更多)分组

时间:2019-09-04 08:17:54

标签: java java-8 functional-programming java-stream vavr

如果我必须使用Stream根据两个不同的字段生成两组,这是我可以采用的一种方法:

var prop1Group = beans.stream().collect(Collectors.groupingBy(Bean::getProp1));
var prop2Group = beans.stream().collect(Collectors.groupingBy(Bean::getProp2));

但是这种方法会遍历整个列表两次。 以命令方式,我可以在单次迭代中获得相同的结果,如下所示:

var prop1Group = new HashMap<String, Set<Bean>>();
var prop2Group = new HashMap<String, Set<Bean>>();

for (var bean : beans) {
    prop1Group.computeIfAbsent(bean.getProp1(), key -> new HashSet<>()).add(bean);
    prop2Group.computeIfAbsent(bean.getProp2(), key -> new HashSet<>()).add(bean);
}

是否有必要使用流以声明方式完成相同的工作,而无需重复两次?

2 个答案:

答案 0 :(得分:1)

根据@Holger的评论,我可以像这样通过teeing更加声明性地编写它,但这仍然要花费2N

=ARRAYFORMULA(IFERROR(REGEXEXTRACT(A2:A, "Verify Pending (\d+)")))

答案 1 :(得分:1)

既然您已经添加了vavr作为标签,我还想添加另一种解决方案,即使用元组,模式匹配和折叠:

var result = list.foldLeft(
      Tuple.of(List.empty(), List.empty()),
      (lists, element) -> Match(element).of(
           Case($(Bean::getProp1), lists.map1(l -> l.append(element))),
           Case($(Bean::getProp2), lists.map2(l -> l.append(element)))
));

在这种情况下,组将存储为Tuple2的字段。