如何用LinkedhashMap用流替换HashMap?

时间:2018-10-29 00:33:05

标签: java lambda java-stream linkedhashmap collectors

您能帮我对我的Map进行排序吗?

我具有以下结构,并且我想以LinkedHashMap的形式按价值相反的顺序组装应用程序。

[{
  "CUSTOMER_1": {
    "APP_1": "1"
  },
  "CUSTOMER_2": {
    "APP_1": "2",
    "APP_3": "7",
    "APP_2": "3"
  }
}]

我已经有一个组装地图的lambda:

 final Map<String, Map<String, Long>> organizationApps = taskHandles.stream().map(this::mapPayload)
            .flatMap(e -> e.entrySet().stream())
            .collect(groupingBy(Map.Entry::getKey, of(HashMap::new,
                    (r, t) -> t.getValue().forEach((k, v) -> r.merge(k, v, Long::sum)),
                    (r1, r2) -> {
                        r2.forEach((v1, v2) -> r1.merge(v1, v2, Long::sum));
                        return r1;
                    }))
            );

我现在需要的是将organizationApps表示的HashMap值替换为LinkedHashMap,然后按正确的顺序将这些值放入LinkedHashMap中。

如何在lambda中做到这一点?

UPD:

我可以用以下代码实现必要的输出:

    final Map<String, Map<String, Long>> organizationApps = taskHandles.stream().map(this::mapPayload)
            .flatMap(e -> e.entrySet().stream())
            .collect(groupingBy(Map.Entry::getKey, of(HashMap::new,
                    (r, t) -> t.getValue().forEach((k, v) -> r.merge(k, v, Long::sum)),
                    (r1, r2) -> {
                        r2.forEach((v1, v2) -> r1.merge(v1, v2, Long::sum));
                        return r1;
                    }))
            );

    organizationApps.forEach((key, value) -> {
        final Map<String, Long> sorted = value.entrySet()
                .stream()
                .sorted(reverseOrder(Map.Entry.comparingByValue()))
                .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
                        LinkedHashMap::new));
        organizationApps.put(key, sorted);
    });

如何在一个λ中做到这一点?

1 个答案:

答案 0 :(得分:2)

在创建按结果值排序的LinkedHashMap之前,您不能避免将值收集到映射中,但是您可以将转换步骤指定为自定义的 finisher 函数收集器:

Map<String, Map<String, Long>> organizationApps = input.stream()
    .flatMap(e -> e.entrySet().stream())
    .collect(groupingBy(Map.Entry::getKey, Collector.of(HashMap::new,
        (r, t) -> t.getValue().forEach((k, v) -> r.merge(k, v, Long::sum)),
        (r1, r2) -> {
            r2.forEach((v1, v2) -> r1.merge(v1, v2, Long::sum));
            return r1;
        },
        (Map<String, Long> m) -> m.entrySet().stream()
            .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
            .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
                LinkedHashMap::new))
    )));

等同于以下(Java 9+)代码

Map<String, Map<String, Long>> organizationApps = input.stream()
    .flatMap(m -> m.entrySet().stream())
    .collect(groupingBy(Map.Entry::getKey, collectingAndThen(flatMapping(
            t -> t.getValue().entrySet().stream(),
            toMap(Map.Entry::getKey, Map.Entry::getValue, Long::sum)),
        (Map<String, Long> m) -> m.entrySet().stream()
            .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
            .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
                LinkedHashMap::new))
    )));

this answer的末尾是flatMapping收集器的Java 8兼容实现,但是您的自定义收集器也可以完成该工作。