如果您正在寻找一种即用型数据结构,它存储 元素和计数,那么 Guava's Multiset 正是这样做的。
如果您只需要将列表转换为计数图,请继续阅读。
您可以使用 Java 8 Streams API 在单个语句中将列表转换为计数映射:
final var list = List.of("12345", "34578", "12345", "98710", "12345");
final var counts = list.stream()
.collect(Collectors.toMap(
Function.identity(), // Map keys are list elements
value -> 1, // Map values are counts, a single item counts "1"
(count1, count2) -> count1 + count2 // On duplicate keys, counts are added
));
在底层,此解决方案使用哈希映射(元素到计数)作为数据结构。
您也可以使用groupingBy 收集器,正如Peter Lawrey 所建议的那样:
final var list = List.of("12345", "34578", "12345", "98710", "12345");
final var counts = list.stream()
.collect(Collectors.groupingBy(
Function.identity(), // Group the elements by equality relation
Collectors.counting() // Map values are counts of elements in the equality groups
));
有时(在学习时)“手动”实现所有内容以理解算法是有益的。所以这里的版本没有 Java 8 的好东西,比如流、收集器和新的地图方法,比如 Map.compute():
final List<Stream> list = List.of("12345", "34578", "12345", "98710", "12345"); // Use ArrayList if you're below Java 9
final Map<String, Integer> counts = new HashMap<>();
for (final String item : list) {
// Note: I'm deliberately NOT using Map.compute() here
// to demonstrate how to do everything "manually"
Integer count = counts.get(item);
if (count == null) {
count = 0;
}
counts.put(item, count + 1);
}