【问题标题】:Sort by nested Array size inside nested Map按嵌套 Map 内的嵌套数组大小排序
【发布时间】:2016-04-26 12:10:18
【问题描述】:

大家好, 我的任务是按嵌套数组大小/长度的降序对 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()))

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

任何想法为什么我的排序失败?感谢您的帮助,我很感激。

【问题讨论】:

  • 排序失败的原因是什么?
  • 排序返回的是嵌套地图的大小,而不是嵌套地图内的数组大小。
  • classes 映射中有多个与键关联的数组。您需要聚合长度值。按平均值、总和、中位数排序?您的示例似乎是根据map 的大小而不是包含数组的大小进行排序的。
  • 你想在控制台打印什么?所有ArrayList 按大小排序?我还提到Map 不是有序集合。
  • 我想以这种方式打印整个结构,以便每个主键都按从键的数组大小排序,例如:

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


【解决方案1】:

希望我不是在说显而易见的,但鉴于您提供的信息,我假设您希望 .sorted() 对原始集合进行排序。

因为你正在使用 Stream 不会修改原始集合。 .sorted() 返回一个新的集合。使用它的结果。

【讨论】:

  • 好吧,它会返回一个排序好的Stream。它仍然必须被收集到一个集合中(支持排序)。
  • 我对地图进行排序只是为了在控制台上打印它。我不打算以任何方式修改原件。
【解决方案2】:

您的问题未详细说明。如果值是Maps,您不能只说要按列表的大小排序,因为每个Map 中可以有任意数量的列表。您在 cmets 中给出的示例没有说明任何内容,因为它根本没有解决该问题。如果您假设“从属”映射的大小始终为 1,则应明确指定。否则,您必须汇总大小。

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

因此,对列表大小求和的解决方案可能如下所示

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

请注意,如果每个“从属”映射中只有一个列表,则此聚合也有效。

为了完整起见,请注意,专门用于排序地图条目,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()),用于映射值可比较的最简单的情况。

【讨论】:

    【解决方案3】:

    感谢 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()))
    

    【讨论】:

      猜你喜欢
      • 2021-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多