计算列表中字符串的出现次数,然后对结果进行排序-Java 8

计算列表中字符串的出现次数,然后对结果进行排序-Java 8,java,sorting,java-8,java-stream,collectors,Java,Sorting,Java 8,Java Stream,Collectors,我看到这种“计数事件和排序”类型的问题有很多种(最密切相关的问题是),但没有一种在我的情况下有效 这是我的密码 List<Employee> employees = new ArrayList<>(); Employee e1 = new Employee; e1.setFirstName("Beth"); Employee e2 = new Employee; e1.setFirstName("Beth"); Employee e3 = new Employee;

我看到这种“计数事件和排序”类型的问题有很多种(最密切相关的问题是),但没有一种在我的情况下有效

这是我的密码

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()));
但我也需要它

{Alex=2345562, Andrew=34674, Beth=2, Charles=2388491, John=223545}
我试过这个:

Map employeeFirstNameCount=employees.stream()
.collect(Collectors.groupingBy(p->p.getFirstName(),Collectors.counting())
.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.naturalOrder())。然后比较(Map.Entry.comparingByKey())
.限额(20)
.map(map.Entry::getKey)
.collect(toList());
但是得到这个错误


现在我不知所措。有人能帮忙吗

由于您希望结果为
Map
,因此不应映射到条目键,即
.Map(Map.entry::getKey)
,我们也不应收集到列表,即
.collect(toList())
,因为最终您将得到的是
列表,而不是
Map
,而是在按照指定的条件进行排序之后,您应该收集到一个映射,尤其是
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));

如果在创建
Map
时使用
TreeMap
而不是默认的
HashMap
,则可以获得所需的输出,如下所示:

Map<String, Long> employeeFirstNameCount = employees.stream()
            .collect(Collectors.groupingBy(Employee::getFirstName,
                                           TreeMap::new,
                                           Collectors.counting()));
Map employeeFirstNameCount=employees.stream()
.collect(收集器).groupingBy(雇员::getFirstName,
树映射::新的,
收集器。计数();
java.util.TreeMap
使用其键的自然顺序(这足以满足您的需要),或者您可以提供自定义的
比较器


注意:我使用lambda表达式
Employee::getFirstName
而不是
p->p.getFirstName()
,但两者产生相同的结果。

您正在使用
toList()
创建一个
列表,但您正在为声明为
Map
的变量赋值。我尝试了您的代码。我的错误已经消失,但结果仍然没有分类(AfAsiaEngEd.我已经根据预期的结果改变了比较器。如果你仍然没有得到你想要的,然后考虑确切地说出你想要排序的……即值,然后按关键字,按值下降,然后由键……我找出为什么我没有看到排序结果。代码>新建JSONObject(employeeFirstNameCount).toString(2)
以正确查看结果。这再次打乱了顺序,但在调试期间,我确认
employeeFirstNameCount
中的值实际上已排序。我尝试了您的以及@DSantiagoBC的解决方案,两种方法都很有效。感谢您的帮助!添加TreeMap确实更改了某些名称的顺序,但顺序仍然未排序。TreeMap按键排序,由于重复的键不可能存在,因此无需按值排序。方法keySet()、values()、toString()、entrySet()都返回按键结果排序的结果。我找出了为什么看不到排序的结果。根据代码创建映射后,我正在执行
新建JSONObject(employeeFirstNameCount)。toString(2)
以正确查看结果。这再次打乱了顺序,但在调试过程中,我确认
employeeFirstNameCount
中的值实际上已排序。我尝试了您的以及@Aomine的解决方案,两者都很好。感谢您的帮助!顺便说一句,我保留了p->p.getFirstName。并且使用您的解决方案,因为它比较短.
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));
employees.stream()
         .sorted(Comparator.comparing(Employee::getFirstName))
         .collect(Collectors.groupingBy(Employee::getFirstName,
                        LinkedHashMap::new,
                        Collectors.counting()));
Map<String, Long> employeeFirstNameCount = employees.stream()
            .collect(Collectors.groupingBy(Employee::getFirstName,
                                           TreeMap::new,
                                           Collectors.counting()));