按嵌套地图中的列表大小对外部地图Map<String, Map<String, List<Integer>>>
进行排序,保留外键和内键,如前所述。
答案 0 :(得分:2)
您可以通过概括流程来解决此问题:
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
,其中Integer
代表其大小,并按降序排序,并使用替换操作作为外部地图的替换函数:< / p>
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()
以进行比较。