Слияние, сортировка и лимит карты потоков с использованием Java 8


У меня две карты карта1 и карта2 . Я хочу объединить обе карты, а затем отсортировать в порядке desc и сделать топ-5. В случае дубликаты ключей в слиянии мне нужно просуммировать значения. У меня есть следующий код, который работает:

Map<String, Long> topFive = (Stream.concat(map1.entrySet().stream(), map2.entrySet().stream())
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Long::sum)))
        .entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
        .limit(5).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
            (v1,v2) -> v1,
            LinkedHashMap::new));

Но я хотел бы знать, если существует лучшее решение.



875
1
задан 22 марта 2018 в 05:03 Источник Поделиться
Комментарии
2 ответа

Вопрос на "лучшее" решение, обязан быть достаточно отзывов. Насколько код идет, я думаю, что вы достаточно близки к оптимальному. Что касается читабельности... ну, Роланд уже рассказал о своих первоначальных мыслей и я полностью согласен. Это должно быть кошмаром для бедных программист техническое обслуживание.

Таким образом, предложение в которой нет ничего нового, но просто немного rearangement:

private Map<String, Long> getHistogramTopFive(Map<String, Long> map1, Map<String, Long> map2) {
Map<String, Long> mergedMap = (Stream.concat(map1.entrySet().stream(), map2.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Long::sum)));

Map<String, Long> topFive = mergedMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(5)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(v1,v2) -> v1,
LinkedHashMap::new));

return topFive;
}

Помещая его в способ и называя этот метод, вы документировать свои бизнес-намерения. Кроме того, путем ломать вверх по длинной командной цепочке с новой mergedMap переменная в период, кода приобретает очень в читабельности.

Дополнительную строку-брейков во второй части то, что я считаю лучшей практики в потоковый API: каждой новой работы на новой строке.

1
ответ дан 22 марта 2018 в 06:03 Источник Поделиться

Когда я впервые увидел код, это выглядело пугающим, потому что он представляет собой сплошной прямоугольник символов, без какой-либо видимой структуры. Похоже, вы написали роман в одном пункте.

Затем я сделал глубокий вдох и медленно прочитать код от начала до конца, что заставило меня подумать: Да, это именно то, что вы deccibed в природной язык. Жаль, что код гораздо больше, чем ваше описание.

В основном вы имеете дело с гистограммой, которая представляет собой Map<T, Long> отсортированный по значениям. Поэтому, попробовать найти стороннюю библиотеку, которая предлагает классу гистограммы, а затем ваш код может читать:

var topFive = Histogram.create(map1).addAll(map2).top(5);

Я не знаю такой библиотеки из верхней части моей головы, но она, безусловно, существует.

0
ответ дан 22 марта 2018 в 05:03 Источник Поделиться