如何按内部对象Address的street和city字段对List<Man>进行分组?
按Address的street和city分组List的实现方法
嘿,这个问题用Java的Stream API就能轻松解决!先给你梳理几种实用的方案,先假设你的两个类结构大概是这样(如果和你的实际类有出入,调整getter就行):
class Man { private String name; private Address address; // 构造器、toString等省略 public Address getAddress() { return address; } } class Address { private String street; private String city; // 构造器、toString等省略 public String getStreet() { return street; } public String getCity() { return city; } }
方案1:自定义分组Key类(兼容所有Java版本)
因为要同时用street和city作为分组依据,我们可以自定义一个类来封装这两个字段,必须重写equals()和hashCode()方法——这是分组的关键,因为groupingBy底层用HashMap判断Key是否相同,完全依赖这两个方法。
import java.util.Objects; import java.util.List; import java.util.Map; import java.util.stream.Collectors; class AddressKey { private final String street; private final String city; public AddressKey(String street, String city) { this.street = street; this.city = city; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AddressKey that = (AddressKey) o; return Objects.equals(street, that.street) && Objects.equals(city, that.city); } @Override public int hashCode() { return Objects.hash(street, city); } // 可选:重写toString,方便打印查看分组结果 @Override public String toString() { return street + " | " + city; } } // 执行分组逻辑 public static void main(String[] args) { List<Man> manList = // 初始化你的Man集合 Map<AddressKey, List<Man>> groupedMap = manList.stream() .collect(Collectors.groupingBy(man -> new AddressKey(man.getAddress().getStreet(), man.getAddress().getCity()) )); }
方案2:用Java自带的SimpleEntry(无需自定义类)
如果不想额外写类,可以直接用AbstractMap.SimpleEntry,它已经帮我们实现了equals()和hashCode(),拿来当分组Key刚好合适:
import java.util.AbstractMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; // 执行分组逻辑 public static void main(String[] args) { List<Man> manList = // 初始化你的Man集合 Map<AbstractMap.SimpleEntry<String, String>, List<Man>> groupedMap = manList.stream() .collect(Collectors.groupingBy(man -> new AbstractMap.SimpleEntry<>(man.getAddress().getStreet(), man.getAddress().getCity()) )); }
方案3:用Java 16+的Record(最简洁)
Java 16引入的Record可以自动生成equals()、hashCode()和toString(),代码会非常简洁清爽:
import java.util.List; import java.util.Map; import java.util.stream.Collectors; // 定义一个Record作为分组Key record AddressKey(String street, String city) {} // 执行分组逻辑 public static void main(String[] args) { List<Man> manList = // 初始化你的Man集合 Map<AddressKey, List<Man>> groupedMap = manList.stream() .collect(Collectors.groupingBy(man -> new AddressKey(man.getAddress().getStreet(), man.getAddress().getCity()) )); }
关键注意点
不管用哪种方案,核心都是:分组的Key必须能正确标识“相同的street+city组合”,也就是必须保证两个Key的street和city都相同时,equals()返回true,hashCode()返回相同值——不然分组会把本该同组的元素分到不同组里,这点一定要注意哦!
内容的提问来源于stack exchange,提问作者Andrew Valevskiy
相关产品推荐
相关产品推荐

