按嵌套Map中的嵌套数组大小排序

时间:2016-04-26 12:10:19

标签: java sorting lambda java-8 java-stream

Hy大家, 我的任务是按嵌套数组大小/长度的降序排序Java Map,但嵌套数组在嵌套Map中。结构如下:

HashMap<String, HashMap<String, ArrayList<String>>> classes = new HashMap<>();

我正在使用lambda,我尝试了很多变种,包括:

classes.entrySet().stream()
            .sorted((k1, k2) -> Long.compare(classes.get(k2.getKey()).entrySet().stream().count(), classes.get(k1.getKey()).entrySet().stream().count()))

classes.entrySet().stream()
            .sorted((k1, k2) -> Integer.compare(k2.getValue().values().size(), k1.getValue().values().size()))

但没有任何运气。由于数据的性质,我不能使用其他数据结构,我必须坚持使用这个。

为什么我的排序失败了?感谢您的帮助,我很感激。

3 个答案:

答案 0 :(得分:1)

希望我没有陈述显而易见的内容,但鉴于您提供的信息,我假设您希望.sorted()对原始收藏品进行排序。<\ n / p>

因为您正在使用     Stream 原始系列不会被修改。     .sorted() 返回一个新集合。使用结果。

答案 1 :(得分:0)

您的问题未得到充分说明。如果值为Map s,则不能仅仅表示您希望按其列表大小排序,因为每个Map中可以有任意数量的列表。您在评论中给出的示例并未澄清任何内容,因为它根本没有解决该问题。如果您假设“slave”映射的大小始终为1,则应明确指定。否则,您必须汇总大小。

进一步注意static接口中有Comparator个方法,用于根据要比较的元素的属性创建比较器,因此您无需编写代码来提取属性两次。

因此,总结列表大小的解决方案可能看起来像

classes.entrySet().stream()
    .sorted(Comparator.comparingInt(e -> e.getValue().values()
                                          .stream().mapToInt(Collection::size).sum()))
    .forEach(System.out::println);

请注意,如果每个“slave”映射中只有一个列表,则此聚合也可以使用。

为了完整,请注意,专门用于排序地图条目,Map.Entry界面中有比较工厂,可以像

一样使用
classes.entrySet().stream()
    .sorted(Map.Entry.comparingByValue(Comparator.comparingInt(
        m -> m.values().stream().mapToInt(Collection::size).sum())))
    .forEach(System.out::println);

虽然在这种特殊情况下使用它没有任何好处。但如果实际值比较器更简单,它可能会改善代码。对于地图值具有可比性的最简单的情况,甚至还有一个无参数变量(即Map.Entry.comparingByValue())。

答案 2 :(得分:0)

感谢Holger,我设法通过更多的实验找到了合适的解决方案:对我有用的是

classes.entrySet().stream()
            .sorted((k1, k2) -> Integer.compare(k2.getValue().values().stream()
                            .mapToInt(Collection::size).sum(),
                    k1.getValue().values().stream()
                            .mapToInt(Collection::size).sum()))