Сортировать внешнюю карту по значению вложенной карты - PullRequest
0 голосов
/ 08 июня 2018

Сортировка внешней карты Map<String, Map<String, List<Integer>>> по размеру списка в вложенной карте с сохранением внешнего и внутреннего ключей, как и раньше.

1 Ответ

0 голосов
/ 08 июня 2018

Вы можете решить эту проблему, обобщив процесс:

private static <K,V,R> Map<K,R>
                       replaceAndSortValues(Map<K,V> m, Function<V,R> f, Comparator<R> c) {
    return m.entrySet().stream()
        .map(e -> Map.entry(e.getKey(), f.apply(e.getValue())))
        .sorted(Map.Entry.comparingByValue(c.reversed()))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                                  (a,b) -> { throw new AssertionError(); },
                                  LinkedHashMap::new));
}

Этот метод создает новую карту с теми же ключами, что и указанная, заменяя все значения с помощью указанной функции и сортируя записи в соответствии собращение указанного компаратора.Он использует фабрику Java 9 Map.entry(…, …).Если вам нужно поддерживать ключи или значения Java 8 или null, вы можете вместо этого использовать new AbstractMap.SimpleImmutableEntry<>(…, …).

Этот метод теперь можно использовать для замены List s вашей внутренней карты на Integer s, представляющихих размеры и сортируйте их в порядке убывания и используйте операцию замены в качестве функции замены внешней карты:

public static Map<String, Map<String, Integer>>
              getCallWithStateSizeGroup(ThreadDumpDo threadDumpDo) {
    return replaceAndSortValues(getCallStackWithStateGroup(threadDumpDo),
        m -> replaceAndSortValues(m, List::size, Comparator.<Integer>naturalOrder()),
        Comparator.comparing(m -> m.values().iterator().next()));
}

Это в основном то же самое, что и ваше опубликованное решение.Компаратор внешней карты использует тот факт, что новые внутренние карты уже отсортированы, поэтому их первое значение является максимальным.Но не должно быть пустой внутренней карты.

Это можно легко приспособить, чтобы сохранить List<ThreadDo> и просто отсортировать их по размеру:

public static Map<String, Map<String, List<ThreadDo>>>
              getCallWithStateSizeGroup(ThreadDumpDo threadDumpDo) {
    return replaceAndSortValues(getCallStackWithStateGroup(threadDumpDo),
        m -> replaceAndSortValues(m, Function.identity(),
                                  Comparator.comparingInt(List::size)),
        Comparator.comparingInt(m -> m.values().iterator().next().size()));
}

Нам нужно только изменить внутреннюю картузамените функцию на Function.identity() и предоставьте компаратор, используя размеры списка.Компаратор внешней карты все еще может использовать тот факт, что внутренние карты уже отсортированы в этой точке, но также должен извлечь size() из списка для сравнения.

...