按嵌套映射的值对外部映射进行排序

按照以前保留外键和内键的嵌套映射中的列表大小外部映射Map<String, Map<String, List>>进行排序

您可以通过概括过程来解决这个问题:

 private static  Map replaceAndSortValues(Map m, Function f, Comparator 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表示其大小,并按降序排序,并使用替换操作作为外部映射的替换函数:

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

这与您发布的解决方案基本相同。 外部地图的比较器使用新内部地图已经排序的事实,因此它们的第一个值是最大值。 但是必须没有空的内部地图。

这很容易适应保持List并按大小排序:

 public static Map>> 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()以进行比较。