java - 在 Java 8 中递归展平嵌套映射的值

标签 java java-8 java-stream flatten

给定一个 Map<String, Object> ,其中的值为 String或另一个 Map<String, Object> ,如何使用 Java 8 将映射扁平化为单个值列表?

例子:

Map - "key1" -> "value1"
    - "key2" -> "value2"
    - "key3" -> Map - "key3.1" -> "value3.1"
                    - "key3.2" -> "value3.2"
                    - "key3.3" -> Map - "key3.3.1" -> "value3.3.1"
                                      - "key3.3.2" -> "value3.3.2" 

对于上面的例子,我想要下面的列表:

value1
value2
value3.1
value3.2
value3.3.1
value3.3.2

我知道可以这样做:

public static void main(String args[]) throws Exception {
    //Map with nested maps with nested maps with nested maps with nested......
    Map<String, Object> map = getSomeMapWithNestedMaps();

    List<Object> values = new ArrayList<>();
    addToList(map, values);

    for (Object o:values) {
        System.out.println(o);
    }
}

static void addToList(Map<String, Object>map, List<Object> list) {
    for (Object o:map.values()) {
        if (o instanceof Map) {
            addToList((Map<String, Object>)o, list);
        } else {
            list.add(o);
        }
    }
}

我如何使用 Stream 执行此操作? ?

编辑:

经过一番尝试后,我想通了:

public static void main(String args[]) throws Exception {
    //Map with nested maps with nested maps with nested maps with nested......
    Map<String, Object> map = getSomeMapWithNestedMaps();
    //Recursively flatten maps and print out all values
    List<Object> list= flatten(map.values().stream()).collect(Collectors.toList());
}

static Stream<Object> flatten(Stream<Object> stream) {
    return stream.flatMap((o) ->
        (o instanceof Map) ? flatten(((Map<String, Object>)o).values().stream()) : Stream.of(o)
    );
}

最佳答案

您可以定义一个递归方法来展平一个 map 并将其用作 Stream#flatMap 的函数或通过直接调用它来使用它。

例子:

public class FlatMap {

    public static Stream<Object> flatten(Object o) {
        if (o instanceof Map<?, ?>) {
            return ((Map<?, ?>) o).values().stream().flatMap(FlatMap::flatten);
        }
        return Stream.of(o);
    }

    public static void main(String[] args) {
        Map<String, Object> map0 = new TreeMap<>();
        map0.put("key1", "value1");
        map0.put("key2", "value2");
        Map<String, Object> map1 = new TreeMap<>();
        map0.put("key3", map1);
        map1.put("key3.1", "value3.1");
        map1.put("key3.2", "value3.2");
        Map<String, Object> map2 = new TreeMap<>();
        map1.put("key3.3", map2);
        map2.put("key3.3.1", "value3.3.1");
        map2.put("key3.3.2", "value3.3.2");

        List<Object> collect = map0.values().stream()
                                            .flatMap(FlatMap::flatten)
                                            .collect(Collectors.toList());
        // or
        List<Object> collect2 = flatten(map0).collect(Collectors.toList());
        System.out.println(collect); 
    }
}

对于给定的嵌套映射,它打印

[value1, value2, value3.1, value3.2, value3.3.1, value3.3.2]

关于java - 在 Java 8 中递归展平嵌套映射的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37462264/

相关文章:

java - 使用 Java 8 Stream API 时如何移至循环中的下一个值

java - 为同一个 Titan Graph 创建多个实例

java-8 - Java 11 中的空方法明显比 Java 8 慢

java - 将 Set<V> 转换为 Map<String, Set<String>

java - 如何在 UnaryOperator java 8 中使用引用方法

java - Clojure 转换器与 Java 中流的中间操作的概念相同吗?

具有过滤条件工作流程的 Java 8 流

java - 使用 Java 8 Stream API 合并两个 Map<String, Integer>

java - 如果只有一个选项卡存在,有没有办法隐藏 JTabbedPane 的选项卡栏?

java - 如何反序列化avro文件