【问题标题】:How to sort outer map by nested map value如何按嵌套地图值对外部地图进行排序
【发布时间】:2019-07-02 12:28:11
【问题描述】:

我遇到了 Java 8 排序方法的问题。

我得到以下结构:

Map<String, Map<String, Long>>

我想要实现的是首先按外部映射的键(强制顺序)对外部映射进行排序,然后按内部映射值的总和(Longs),并以正确的顺序将其放入 Map.Entry 列表中。我设法使用第一个条件对其进行排序,但我无法使其在第二个条件下工作(thenComparing 方法) - 存在类型错误。

queryResult.allCountersArray = queryResult.allCounters.entrySet().stream()
        .sorted(Map.Entry.<String, Map<String, Long>>comparingByKey(Comparator.comparing(term -> term.getSortingKey()))
                .thenComparing(Map.Entry.<String, Map<String, Long>>comparingByValue(Map.Entry.<String, Long>comparingByValue()))
        )
        .collect(Collectors.toList());


Error:(87, 49) java: no suitable method found for comparingByValue(java.util.Comparator<java.util.Map.Entry<java.lang.String,java.lang.Long>>)
    method java.util.Map.Entry.<K,V>comparingByValue() is not applicable
      (explicit type argument java.util.Map<java.lang.String,java.lang.Long> does not conform to declared bound(s) java.lang.Comparable<? super java.util.Map<java.lang.String,java.lang.Long>>)
    method java.util.Map.Entry.<K,V>comparingByValue(java.util.Comparator<? super V>) is not applicable
      (argument mismatch; java.util.Comparator<java.util.Map.Entry<java.lang.String,java.lang.Long>> cannot be converted to java.util.Comparator<? super java.util.Map<java.lang.String,java.lang.Long>>)

【问题讨论】:

  • 然后按内部映射值...:从技术上讲,内部映射将有多个键/值对。您想在排序中使用哪一个?
  • 我很难解释这一点。我尝试按这些内部 Long 的总和对其进行排序。我现在正在编辑问题。
  • 也许添加一个示例(输入 --> 预期输出)?

标签: java sorting java-stream


【解决方案1】:

在这种情况下,您不能使用 comparingByValue,因为您不想按内部映射的各个条目进行排序。

你能做的最好的就是:

List<Entry<String, Map<String, Long>>> result = queryResult.entrySet()
        .stream()
        .sorted(Comparator.comparing(Entry<String, Map<String, Long>>::getKey)
                .thenComparingLong(e -> e.getValue()
                        .values()
                        .stream()
                        .mapToLong(i -> i)
                        .sum()))
        .collect(Collectors.toList());

或者

List<Entry<String, Map<String, Long>>> result2 = queryResult.entrySet()
        .stream()
        .sorted(Entry.<String, Map<String, Long>>comparingByKey()
                .thenComparingLong(e -> e.getValue()
                        .values()
                        .stream()
                        .mapToLong(i -> i)
                        .sum()))
        .collect(Collectors.toList());

【讨论】:

  • @voidmat 我确定您可以将.reversed() 添加到thenComparing() 表达式中(现在无法测试,但理论上应该可以)
  • 我刚刚使用 thenComparing,第一个参数是你的函数(来自 thenComparingLong 的参数)和第二个参数 Comparator.reverseOrder()。
  • OP 可以在提供正确的值比较器时使用comparingByValue,这与您的比较器的不同之处仅在于不需要第一个getValue() 调用。但是由于 Map 的所有键都是不同的,因此在使用 Entry.&lt;String, Map&lt;String, Long&gt;&gt;comparingByKey() 时,整个二级排序标准无论如何都已过时。
【解决方案2】:

这应该可行:

final Map<String, Map<String, Long>> map = new HashMap<>();

final List<Entry<String, Map<String, Long>>> sorted = 
    map.entrySet().stream().sorted((a,  b) -> Long.compare(
        a.getValue().values().stream().mapToLong(l -> l).sum(),
        b.getValue().values().stream().mapToLong(l -> l).sum()))
    .collect(Collectors.toList());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 2016-10-25
    • 2020-09-13
    • 1970-01-01
    • 2020-04-22
    • 2013-10-31
    • 1970-01-01
    相关资源
    最近更新 更多