如何使用Stream的groupingBy方法按嵌套对象C.id分组List<A>
嘿,这个需求很常见,我来给你拆解一下怎么用Java Stream的groupingBy搞定它。
首先得明确你的对象层级:A包含B,B包含C,所以每个A实例都能通过A.getB().getC()拿到对应的C对象。我们要把List<A>按C分组为Map<C, List<A>>,核心其实就两步:
1. 确保C类正确实现equals()和hashCode()
这一步非常关键!因为groupingBy默认使用HashMap来存储分组结果,而HashMap是通过equals()和hashCode()来判断两个C对象是否相等的。如果你的分组逻辑是基于C.id(也就是id相同的C就算同一个分组key),那你的C类必须基于id来实现这两个方法:
import java.util.Objects; class C { private Long id; // 其他字段、getter、setter @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; C c = (C) o; return Objects.equals(id, c.id); } @Override public int hashCode() { return Objects.hash(id); } }
如果不做这一步,哪怕两个C对象的id相同,只要是不同的实例,HashMap都会把它们当成不同的key,分组结果就会出错。
2. 用Stream的groupingBy完成分组
这一步就很直接了,调用stream()后,用Collectors.groupingBy()传入提取C对象的lambda表达式即可:
List<A> listOfA = ...; // 你的A集合实例 Map<C, List<A>> groupedMap = listOfA.stream() .collect(Collectors.groupingBy(a -> a.getB().getC()));
额外处理:避免空指针异常
如果你的业务场景中,A的B或者B的C可能为null,那上面的代码会抛出NullPointerException。这时候你可以先过滤掉这些无效元素:
Map<C, List<A>> groupedMap = listOfA.stream() // 过滤掉B或C为null的A实例 .filter(a -> a.getB() != null && a.getB().getC() != null) .collect(Collectors.groupingBy(a -> a.getB().getC()));
如果需要保留这些包含null的元素,可以把它们分到null对应的key下(不过这种场景要根据业务需求来判断是否合理):
Map<C, List<A>> groupedMap = listOfA.stream() .collect(Collectors.groupingBy(a -> { if (a.getB() == null || a.getB().getC() == null) { return null; } return a.getB().getC(); }));
总结一下
- 核心就是
Collectors.groupingBy(a -> a.getB().getC()),但前提是C类的equals()和hashCode()要符合你的分组逻辑。 - 一定要考虑空值情况,避免运行时异常。
内容的提问来源于stack exchange,提问作者iamP
相关产品推荐
相关产品推荐

