Stream API sorted/foreach

109
09 марта 2021, 17:00
public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        Stream.of(s.split("[^A-Za-zА-Яа-я0-9]+"))
                .map(String::toLowerCase)
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
                .entrySet()
                .stream()
                .sorted(Map.Entry.<String, Long>comparingByKey())/*.thenComparing(Map.Entry.<String, Long>comparingByValue().reversed())*/
                .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
                .limit(10)
                .forEach(x -> System.out.println(x.getKey()));
    }

Есть данный код. Суть его такова - пишем в консоль слова через пробел, а программа ищет наиболее часто встречающиеся слова и выводит их в порядке от тех, что встречаются чаще, до тех, что встречаются реже. Также стоит лимит на 10 слов. В случае если несколько слов встречаются одинаковое количество раз, они дополнительно сортируются по алфавиту.

А теперь вопрос - меня беспокоит 2 места в коде:

1) можно ли как-то отсортировать вывод в одной строке? Я пытался (код закоменченный) через thenComparing, но почему-то с такой реализацией сортируется только по алфавиту.

2) я хочу вывести слова через ссылку на метод System.out::println, подскажите пожалуйста, как можно разбить поток пар ключ/значение так, чтобы в потоке остались только ключи

Answer 1

1) Первой нужно указать сортировку по количеству слов, а в thenComparing - по алфивиту

Map.Entry.<String, Long>comparingByValue().reversed().thenComparing(Map.Entry.comparingByKey())   

2) Можно добавить map, в котором будет вызываться getKey:

map(Map.Entry::getKey)

Все вместе будет выглядеть как-то так

 Stream.of(s.split("[^A-Za-zА-Яа-я0-9]+"))
     .map(String::toLowerCase)
     .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
     .entrySet()
     .stream()
     .sorted(Map.Entry.<String, Long>comparingByValue().reversed().thenComparing(Map.Entry.comparingByKey()))
     .map(Map.Entry::getKey)
     .limit(10)
     .forEach(System.out::println);
READ ALSO
Конструкция if..else с отрицательным условием

Конструкция if..else с отрицательным условием

Помогите, пожалуйста, прояснить ситуациюЕсть конструкция вида:

87
Странности JS присваивание

Странности JS присваивание

Почему такая конструкция отработает корректно?

75
Зашифрованый текст JS cfemail

Зашифрованый текст JS cfemail

Всем привет, на сайте есть такая запись:

114