计算列表中字符串的出现次数,然后对结果进行排序 - Java 8
Count occurrences of a String in a List, then sort the result - Java 8
我发现这种 "count occurrences and sort" 类型的问题有很多种(最相关的问题是 ),但其中 none 适合我的情况。
这是我的代码。
List<Employee> employees = new ArrayList<>();
Employee e1 = new Employee;
e1.setFirstName("Beth");
Employee e2 = new Employee;
e1.setFirstName("Beth");
Employee e3 = new Employee;
e1.setFirstName("Andrew");
// similarly I'm creating millions of employees and adding them to my list below
employees.add(e1);
employees.add(e2);
employees.add(e3);
employees.add(e53456667);
//count occurrences of first names
Map<String, Long> employeeFirstNameCount = employees.stream()
.collect(Collectors.groupingBy(p -> p.getFirstName(), Collectors.counting()));
这导致
{Beth=2, Andrew=34674, Charles=2388491, John=223545, Alex=2345562}
但我需要它作为
{Alex=2345562, Andrew=34674, Beth=2, Charles=2388491, John=223545}
我试过了):
Map<String, Long> employeeFirstNameCount = employees.stream()
.collect(Collectors.groupingBy(p -> p.getFirstName(), Collectors.counting()))
.entrySet().stream()
.sorted(Map.Entry.<String, Long> comparingByValue(Comparator.naturalOrder()).thenComparing(Map.Entry.comparingByKey()))
.limit(20)
.map(Map.Entry::getKey)
.collect(toList());
但是出现这个错误
现在我一头雾水。有人可以帮忙吗?
由于您希望结果为 Map<String, Long>
,因此您不应映射到输入键,即 .map(Map.Entry::getKey)
,而且您也不应收集到列表,即 .collect(toList())
因为最终你会得到 List<String>
而不是 Map<String, Long>
,而不是在按指定的标准排序之后,你应该收集到地图,特别是 LinkedHashMap
:
Map<String, Long> result = employees.stream()
.collect(Collectors.groupingBy(p -> p.getFirstName(),
Collectors.counting()))
.entrySet().stream()
.sorted(Map.Entry.<String, Long> comparingByKey())
.limit(20)
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(l,r) -> l,
LinkedHashMap::new));
上面的比较器将仅按键排序,因为这似乎是您的预期结果所暗示的。
注意,如果分组后不需要limit
操作,上面可以简化为:
employees.stream()
.sorted(Comparator.comparing(Employee::getFirstName))
.collect(Collectors.groupingBy(Employee::getFirstName,
LinkedHashMap::new,
Collectors.counting()));
如果在创建 Map
时使用 TreeMap
而不是默认的 HashMap
,则可以获得所需的输出:
Map<String, Long> employeeFirstNameCount = employees.stream()
.collect(Collectors.groupingBy(Employee::getFirstName,
TreeMap::new,
Collectors.counting()));
java.util.TreeMap
使用其键的自然顺序(这足以满足您的需要)或者您可以提供自定义 Comparator
注意我使用 lambda 表达式 Employee::getFirstName
而不是 p -> p.getFirstName()
,但两者产生相同的结果。
我发现这种 "count occurrences and sort" 类型的问题有很多种(最相关的问题是
这是我的代码。
List<Employee> employees = new ArrayList<>();
Employee e1 = new Employee;
e1.setFirstName("Beth");
Employee e2 = new Employee;
e1.setFirstName("Beth");
Employee e3 = new Employee;
e1.setFirstName("Andrew");
// similarly I'm creating millions of employees and adding them to my list below
employees.add(e1);
employees.add(e2);
employees.add(e3);
employees.add(e53456667);
//count occurrences of first names
Map<String, Long> employeeFirstNameCount = employees.stream()
.collect(Collectors.groupingBy(p -> p.getFirstName(), Collectors.counting()));
这导致
{Beth=2, Andrew=34674, Charles=2388491, John=223545, Alex=2345562}
但我需要它作为
{Alex=2345562, Andrew=34674, Beth=2, Charles=2388491, John=223545}
我试过了
Map<String, Long> employeeFirstNameCount = employees.stream()
.collect(Collectors.groupingBy(p -> p.getFirstName(), Collectors.counting()))
.entrySet().stream()
.sorted(Map.Entry.<String, Long> comparingByValue(Comparator.naturalOrder()).thenComparing(Map.Entry.comparingByKey()))
.limit(20)
.map(Map.Entry::getKey)
.collect(toList());
但是出现这个错误
现在我一头雾水。有人可以帮忙吗?
由于您希望结果为 Map<String, Long>
,因此您不应映射到输入键,即 .map(Map.Entry::getKey)
,而且您也不应收集到列表,即 .collect(toList())
因为最终你会得到 List<String>
而不是 Map<String, Long>
,而不是在按指定的标准排序之后,你应该收集到地图,特别是 LinkedHashMap
:
Map<String, Long> result = employees.stream()
.collect(Collectors.groupingBy(p -> p.getFirstName(),
Collectors.counting()))
.entrySet().stream()
.sorted(Map.Entry.<String, Long> comparingByKey())
.limit(20)
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(l,r) -> l,
LinkedHashMap::new));
上面的比较器将仅按键排序,因为这似乎是您的预期结果所暗示的。
注意,如果分组后不需要limit
操作,上面可以简化为:
employees.stream()
.sorted(Comparator.comparing(Employee::getFirstName))
.collect(Collectors.groupingBy(Employee::getFirstName,
LinkedHashMap::new,
Collectors.counting()));
如果在创建 Map
时使用 TreeMap
而不是默认的 HashMap
,则可以获得所需的输出:
Map<String, Long> employeeFirstNameCount = employees.stream()
.collect(Collectors.groupingBy(Employee::getFirstName,
TreeMap::new,
Collectors.counting()));
java.util.TreeMap
使用其键的自然顺序(这足以满足您的需要)或者您可以提供自定义 Comparator
注意我使用 lambda 表达式 Employee::getFirstName
而不是 p -> p.getFirstName()
,但两者产生相同的结果。