如何用Java Stream获取城市数量Top3的国家编码?
问题描述
现有City实体包含id、name、countryCode字段,示例数据如下:
id | name | countryCode | ------------------------------ 1 | Berlin | DE | 2 | Munich | DE | 3 | Köln | DE | 4 | Paris | FR | 5 | Kopenhag | DK | ...
需要用Java Stream获取拥有最多城市的前3个countryCode,此前尝试的代码如下,但未达到预期效果:
final Map<String, City> airportCodes2 = airportService.getCities().stream() .map(City::getCountryCode, Function.identity()) .toMap();
正确实现方式
你之前的代码有两个明显问题:
Stream.map()方法只接受一个转换函数参数,传两个参数会直接编译报错- 即便写法正确,用
toMap()会因为同一个countryCode对应多个City实例而抛出IllegalStateException(重复键冲突)
正确实现需要分四步:分组统计、排序、取前N个、提取目标字段,完整代码如下:
import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; // 获取城市列表 List<City> cities = airportService.getCities(); // 1. 按countryCode分组,统计每个国家的城市数量 Map<String, Long> countryCityCount = cities.stream() .collect(Collectors.groupingBy( City::getCountryCode, Collectors.counting() )); // 2. 按城市数量降序排序,取前3个countryCode List<String> top3CountryCodes = countryCityCount.entrySet().stream() .sorted(Map.Entry.<String, Long>comparingByValue(Comparator.reverseOrder())) .limit(3) .map(Map.Entry::getKey) .collect(Collectors.toList());
代码解释
- 分组统计:用
Collectors.groupingBy()按countryCode分组,搭配Collectors.counting()统计每组元素数量,得到键为国家码、值为对应城市数量的Map - 排序:将Map的entry转为Stream后,用
comparingByValue(Comparator.reverseOrder())实现按城市数量从多到少排序 - 取前3个:用
limit(3)截取排序后的前3个元素 - 提取结果:通过
map(Map.Entry::getKey)提取出国家码,最后收集为List
如果需要保留城市数量信息,也可以直接收集排序后的Entry:
List<Map.Entry<String, Long>> top3CountryWithCount = countryCityCount.entrySet().stream() .sorted(Map.Entry.<String, Long>comparingByValue(Comparator.reverseOrder())) .limit(3) .collect(Collectors.toList());
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

