Как преобразовать карту в список в Java 8

Как преобразовать a Map<String, Double> в List<Pair<String, Double>> в Java 8?

Я написал эту реализацию, но она не эффективна

Map<String, Double> implicitDataSum = new ConcurrentHashMap<>();
//....
List<Pair<String, Double>> mostRelevantTitles = new ArrayList<>();
implicitDataSum.entrySet().stream().
                .sorted(Comparator.comparing(e -> -e.getValue()))
                .forEachOrdered(e -> mostRelevantTitles.add(new Pair<>(e.getKey(), e.getValue())));

return mostRelevantTitles;

Я знаю, что он должен работать с помощью .collect(Collectors.someMethod()). Но я не понимаю, как это сделать.

Ответ 1

Ну, вы хотите собрать элементы Pair в List. Это означает, что вам нужно сопоставить ваш Stream<Map.Entry<String, Double>> с Stream<Pair<String, Double>>.

Это делается с помощью операции map:

Возвращает поток, состоящий из результатов применения данной функции к элементам этого потока.

В этом случае функция будет функцией, преобразующей a Map.Entry<String, Double> в Pair<String, Double>.

Наконец, вы хотите собрать это в List, поэтому мы можем использовать встроенный коллекционер toList().

List<Pair<String, Double>> mostRelevantTitles = 
    implicitDataSum.entrySet()
                   .stream()
                   .sorted(Comparator.comparing(e -> -e.getValue()))
                   .map(e -> new Pair<>(e.getKey(), e.getValue()))
                   .collect(Collectors.toList());

Обратите внимание, что вы можете заменить компаратор Comparator.comparing(e -> -e.getValue()) на Map.Entry.comparingByValue(Comparator.reverseOrder()).

Ответ 2

Обратите внимание: если вам нужна эффективная реализация, вы должны подумать об этом:

List<Pair<String, Double>> mostRelevantTitles = 
    implicitDataSum.entrySet()
                   .stream()
                   .map(e -> new Pair<>(e.getKey(), e.getValue()))
                   .collect(Collectors.toList());
mostRelevantTitles.sort(Comparators.comparing(Pair::getSecond, Comparator.reverseOrder()));

Я предполагаю, что ваш класс Pair имеет getSecond getter.

Используя шаг конвейера потока sorted(), вы создаете промежуточный буфер, сохраняете все в этом буфере, преобразуете его в массив, сортируете этот массив, а затем сохраняете результат в ArrayList. Мой подход, хотя и менее функциональный, хранит данные непосредственно в целевой ArrayList, а затем сортирует его на месте без какого-либо дополнительного копирования. Таким образом, мое решение займет меньше времени и промежуточную память.