如何使用 java-streams 将以列表作为值的映射转换为数组 [key1, value1.1, key1, value1.2 … keyM, valueM.N]?

How to convert a Map with Lists as values to an array [key1, value1.1, key1, value1.2 … keyM, valueM.N] using java-streams?

假设您有一个 Map<String, List<String>>,其中的值是列表,例如{{"a"->{1}, "b"->{2,3}}},如何将其转换为数组["a", "1", "b", "2", "b", "3"]

我知道可以用下面的循环来完成,但是如何用 java-streams 来实现呢?

public static String[] flattenMap(Map<String, List<String>> m) {

    List<String> flattened = new ArrayList<>();
    for (Map.Entry<String, List<String>> e : m.entrySet()){
        for (String s: e.getValue())
        {
            flattened.add(e.getKey());
            flattened.add(s);
        }
    }

    return flattened.toArray(String[]::new);
}

不容易。 flatMap 是用来将流中的单个值转换为多个值(并且您希望将 Map.Entry<String, List<String>> 的单个值映射到大量值)。但这更复杂;你不能只是 flatMap x.getValue(),例如this: m.entrySet().stream().flatMap(x -> x.getValue().stream()).... 不会这样做,它只会为您提供每个值,而不是“每个值,每个值都有重复的键”)。那是平面图中的平面图,并且会导致比循环更难阅读的代码。它也会变慢。

绝对没有理由对流执行此操作。锤子很棒。非常有用的工具。但是如果你有一些黄油需要涂抹在你的面包上,也许不要使用锤子:)

但是,嘿,我和下一个人一样喜欢疯狂的壮举。所以,在所有的荣耀中,给你:

var m = new LinkedHashMap<String, List<String>>();
m.put("a", List.of("b", "c"));
m.put("d", List.of("e"));
m.put("f", List.of("g", "h", "i"));

String[] res = m.entrySet().stream().flatMap(x -> 
    x.getValue().stream().flatMap(y -> Stream.of(x.getKey(), y))
).toArray(String[]::new);
System.out.println(Arrays.toString(res));

[a, b, a, c, d, e, f, g, f, h, f, i]