java new 嵌套map_java – 如何使用Collectors.groupingBy创建嵌套Map?

摘要/简要讨论

从面向对象的角度看,有一张地图的地图是有问题的,因为你可能看起来缺少一些抽象(即你可以创建一个封装了嵌套分组结果的类Result).但是,当完全从纯数据导向方法考虑时,它是完全合理的.

所以在这里我提出了两种方法:第一种方法纯粹是面向数据的(使用嵌套的groupingBy调用,因此嵌套映射),而第二种方法更加符合OO,并且在抽象分组标准方面做得更好.只需挑选一个更能代表您的意图和编码标准/传统,更重要的是您最喜欢的那个.

面向数据的方法

对于第一种方法,您可以嵌套groupingBy调用:

Map>>> result = list.stream()

.collect(Collectors.groupingBy(ProductDto::getStatus,

Collectors.groupingBy(ProductDto::getCategory,

Collectors.groupingBy(ProductDto::getType,

Collectors.mapping(

ProductDto::getBooker,

Collectors.toList())))));

如您所见,结果是Map< String,Map< String,Map< String,List< Booker>>>>.这是因为可能存在多个具有相同(状态,类别,类型)组合的ProductDto实例.

此外,由于您需要Booker实例而不是ProductDto实例,我正在调整最后一个groupingBy收集器,以便它返回Bookers而不是productDtos.

关于减少

如果您只需要一个Booker实例而不是List< Booker>作为最内层映射的值,您需要一种方法来减少Booker实例,即通过关联操作将多个实例转换为一个(累积某些属性的总和是最常见的一个).

面向对象的友好方法

对于第二种方法,具有Map< String,Map< String,Map< String,List< Booker>>>>可能被视为不良做法甚至是纯粹的邪恶.因此,您可以只有一个列表映射,而不是拥有列表映射映射的映射,这些映射的键表示要分组的3个属性的组合.

最简单的方法是使用List作为键,因为列表已经提供了hashCode和equals实现:

Map, List> result = list.stream()

.collect(Collectors.groupingBy(

dto -> Arrays.asList(dto.getStatus(), dto.getCategory(), dto.getType()),

Collectors.mapping(

ProductDto::getBooker,

Collectors.toList())))));

如果您使用的是Java 9,则可以使用List.of而不是Arrays.asList,因为List.of会返回完全不可变且高度优化的列表.


版权声明:本文为weixin_39609622原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。