我正在尝试通过使用Java流在以下实体上获取具有最大城市数的3个国家的国家代码:
城市:
id | name | countryCode |
------------------------------
1 | Berlin | DE |
2 | Munich | DE |
3 | Köln | DE |
4 | Paris | FR |
5 | Kopenhag | DK |
...
我尝试了一些东西,但没有像预期的那样工作。那么,什么是最合适的方法来获得前3个国家代码(前3个大多是重复的国家代码)呢?
final Map<String, City> airportCodes2 = airportService.getCities().stream()
.map(City::getCountryCode, Function.identity())
.toMap();
1条答案
按热度按时间0yg35tkg1#
排序
最简单的方法是通过生成
Map<String, Long>
类型的辅助Map,将每个countryCode
与城市计数相关联,从而按countryCode
对数据进行分组。然后在Map条目上生成流,并按 Value 的相反顺序对其进行排序(* 即,按城市计数的降序 *)。
如何实现:
这种方法的时间复杂度是O(n * log n)**,如果要检索的元素数量很小(如
3
),同时数据量很大,这将是不利的。我们可以做得更好。
使用自定义收集器进行部分排序
我们可以使用
PriorityQueue
(该类是JDK提供的 Binary Heap 的实现)执行部分排序,而不是对辅助Map的所有条目进行排序。为此,我们可以使用静态工厂方法
Collector.of()
实现一个自定义收集器。PriorityQueue
的示例将用作收集器的可变容器。来自流的每个Map条目将与堆的 root 元素进行比较。如果元素大于此值(条目包含较大的计数),则将下一个条目添加到队列根。如果超出限制,则应删除根元素。为了使代码可重用,我们可以将其gentrify化。第一部分(创建一个中间Map,其中的值表示键的频率)保持不变。
最小基于堆的收集器数: