Count occurrences of a String in a List, then sort the result - Java 8

AMagic :

I see there are many flavors of this "count occurrences and sort" type of questions (the closest related question was this) but none of them are working in my situation.

This is my code.

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()));

This results in

{Beth=2, Andrew=34674, Charles=2388491, John=223545, Alex=2345562}

But I need it as

{Alex=2345562, Andrew=34674, Beth=2, Charles=2388491, John=223545}

I tried this (reference):

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());

But getting this error

enter image description here

Now I am clueless. Can someone please help?

DSantiagoBC :

You can get the desired output if you use a TreeMap instead of the default HashMap when you create the Map like this:

Map<String, Long> employeeFirstNameCount = employees.stream()
            .collect(Collectors.groupingBy(Employee::getFirstName,
                                           TreeMap::new,
                                           Collectors.counting()));

The java.util.TreeMap uses the natural ordering of its keys (that is enough for what you need) or you can provide a custom Comparator

Note I use the lambda expression Employee::getFirstName instead of p -> p.getFirstName(), but both produce the same result.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=91725&siteId=1