gpt4 book ai didi

Java 8 嵌套(多级)分组依据

转载 作者:太空狗 更新时间:2023-10-29 22:54:12 26 4
gpt4 key购买 nike

我有几个像下面这样的类

class Pojo {
List<Item> items;
}

class Item {
T key1;
List<SubItem> subItems;
}

class SubItem {
V key2;
Object otherAttribute1;
}

我想根据 key1 聚合项目,对于每个聚合,子项目应该按以下方式通过 key2 聚合:

Map<T, Map<V, List<Subitem>>

Java 8 Collectors.groupingBy 嵌套如何实现?

我正在尝试某事,但中途卡住了

pojo.getItems()
.stream()
.collect(
Collectors.groupingBy(Item::getKey1, /* How to group by here SubItem::getKey2*/)
);

注意:这与级联 groupingBy 不同,级联 groupingBy 根据同一对象中的字段进行多级聚合,如所讨论的 here

最佳答案

您不能通过多个键对单个项目进行分组,除非您接受该项目可能出现在多个组中。在这种情况下,您需要执行一种 flatMap 操作。

实现此目的的一种方法是使用 Stream.flatMap 并在收集之前使用临时对保存 ItemSubItem 的组合。由于缺少标准对类型,典型的解决方案是为此使用 Map.Entry:

Map<T, Map<V, List<SubItem>>> result = pojo.getItems().stream()
.flatMap(item -> item.subItems.stream()
.map(sub -> new AbstractMap.SimpleImmutableEntry<>(item.getKey1(), sub)))
.collect(Collectors.groupingBy(AbstractMap.SimpleImmutableEntry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.groupingBy(SubItem::getKey2))));

不需要这些临时对象的替代方法是在收集器中执行 flatMap 操作,但不幸的是,flatMapping直到 Java 9 才会出现。

有了这个,解决方案看起来像

Map<T, Map<V, List<SubItem>>> result = pojo.getItems().stream()
.collect(Collectors.groupingBy(Item::getKey1,
Collectors.flatMapping(item -> item.getSubItems().stream(),
Collectors.groupingBy(SubItem::getKey2))));

如果我们不想等待 Java 9,我们可以在我们的代码库中添加一个类似的收集器,因为它并不难实现:

static <T,U,A,R> Collector<T,?,R> flatMapping(
Function<? super T,? extends Stream<? extends U>> mapper,
Collector<? super U,A,R> downstream) {

BiConsumer<A, ? super U> acc = downstream.accumulator();
return Collector.of(downstream.supplier(),
(a, t) -> { try(Stream<? extends U> s=mapper.apply(t)) {
if(s!=null) s.forEachOrdered(u -> acc.accept(a, u));
}},
downstream.combiner(), downstream.finisher(),
downstream.characteristics().toArray(new Collector.Characteristics[0]));
}

关于Java 8 嵌套(多级)分组依据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39130122/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com