Java groupingBy:使用单个流获取两个(或更多)组
如果我必须使用Stream基于两个不同的字段生成两个组,我可以采用以下方法:Java groupingBy:使用单个流获取两个(或更多)组,java,java-8,functional-programming,java-stream,vavr,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)); 但这种方法会在列表上迭代两次。 以一种强制性的方式,我可以在一次迭代中得到相同的结果,如下所示: v
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);
}
var prop1Group=newhashmap();
var prop2Group=new HashMap();
for(变量bean:bean){
prop1Group.computeIfAbsent(bean.getProp1(),key->newHashSet()).add(bean);
prop2Group.computeIfAbsent(bean.getProp2(),key->newHashSet()).add(bean);
}
还有什么方法可以使用streams以声明的方式完成相同的任务,而不需要重复两次吗?根据@Holger的评论,我可以用teeing更声明性地编写它,就像这样,但这仍然需要2N
beans.stream().collect(
Collectors.teeing(
groupingBy(Bean::getProp1),
groupingBy(Bean::getProp2),
List::of))
既然您已经添加了
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)))
));
在这种情况下,组将存储为Java 12中的Tuple2
字段,但是,我不认为“迭代两次”是普通集合的实际问题。这听起来更像是过早的优化。事实上,考虑到JIT和Hotspot优化器的工作方式,解决方案迭代两次但在内部循环中执行一个操作可能会更快。