Вы можете решить эту проблему, обобщив процесс:
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()
из списка для сравнения.