如何在Java Stream分组时用自定义Comparator对值列表排序?
按relationId分组并生成排序后id列表的Stream实现
需求说明
现有领域对象:
public class MyObj { private Long id; private Long relationId; private Long seq; // getters }
需要将List<MyObj>按relationId分组,生成Map<Long, List<Long>>,其中值为按自定义规则排序后的id列表,已实现MyObjComparator::compare(返回Comparator<MyObj>)用于排序。
解决方案
方法一:分组后对每组排序并提取id
利用Collectors.collectingAndThen先收集分组后的MyObj列表,再排序并映射为id列表:
List<MyObj> list = getMyObjs(); Map<Long, List<Long>> map = list.stream() .collect(Collectors.groupingBy( MyObj::getRelationId, Collectors.collectingAndThen( Collectors.toList(), myObjs -> { // 用自定义比较器对组内MyObj排序 myObjs.sort(MyObjComparator.compare()); // 映射为id列表 return myObjs.stream() .map(MyObj::getId) .collect(Collectors.toList()); } ) ));
方法二:先全局排序再分组(Java 8兼容)
先对整个列表按自定义规则排序,再分组收集id。注意Java 8中groupingBy默认不保留元素顺序,需指定LinkedHashMap作为容器保证值列表有序:
List<MyObj> list = getMyObjs(); Map<Long, List<Long>> map = list.stream() // 全局按自定义比较器排序 .sorted(MyObjComparator.compare()) .collect(Collectors.groupingBy( MyObj::getRelationId, LinkedHashMap::new, // 保证分组后的值列表顺序与排序后的顺序一致 Collectors.mapping(MyObj::getId, Collectors.toList()) ));
注:Java 9及以上版本中,
groupingBy默认保留元素插入顺序,可省略LinkedHashMap::new参数。
内容的提问来源于stack exchange,提问作者Rollsbean
相关产品推荐
相关产品推荐

