为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

qq_遁去的一_1 2019-11-03 04:04:19
我下面有几节课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基于此处讨论的同一对象中的字段进行多级聚合
查看完整描述

3 回答

?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

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


实现此目的的一种方法是Stream.flatMap与临时对一起使用,以容纳和的组合,Item然后SubItem再进行收集。由于不存在标准对类型,因此典型的解决方案是Map.Entry:


Map<T, Map<V, List<SubItem>>> result = pojo.getItems().stream()

    .flatMap(item -> item.subItems.stream()

        .map(sub -> new AbstractMap.SimpleImmutableEntry<>(item, sub)))

    .collect(Collectors.groupingBy(e -> e.getKey().getKey1(),

                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]));

}



查看完整回答
反对 回复 2019-11-04
?
桃花长相依

TA贡献1860条经验 获得超8个赞

如果将分组为Map<T, List<…>>,则T键是唯一的,但是当将多个分组为时Map<T, Map<V, List<…>>>,V键仅在其子图中是唯一的。但是,根据您的输入数据结构和实际目标,这可能(可能)不是问题。

查看完整回答
反对 回复 2019-11-04
  • 3 回答
  • 0 关注
  • 761 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信