Java流:将地图列表转换为集合

8

我有一个列表,其中每个元素都是一个Map:

List< Map<String, List<String>> >

我想使用Java 8的特性将所有列表中的元素(即Map中的值)收集到一个单独的Set中。

例如:

Input:  [ {"a" : ["b", "c", "d"], "b" : ["a", "b"]}, {"c" : ["a", "f"]} ]
Output: ["a", "b", "c", "d", "f"]

谢谢。
4个回答

19
您可以使用一系列的 Stream.mapStream.flatMap
List<Map<String, List<String>>> input = ...;

Set<String> output = input.stream()    // -> Stream<Map<String, List<String>>>
    .map(Map::values)                  // -> Stream<List<List<String>>>
    .flatMap(Collection::stream)       // -> Stream<List<String>>
    .flatMap(Collection::stream)       // -> Stream<String>
    .collect(Collectors.toSet())       // -> Set<String>
    ;

6

使用flatMap函数来实现该目的。

List< Map<String, List<String>> > maps = ...
Set<String> result = maps.stream()
                         .flatMap(m -> m.values().stream())
                         .flatMap(List::stream)
                         .collect(Collectors.toSet());

5

除了基于 .flatMap 的解决方案,另一种选择是将这些子迭代合并到最终的 collect 操作中:

Set<String> output = input.stream()
    .collect(HashSet::new, (set,map) -> map.values().forEach(set::addAll), Set::addAll);

4

对于这个问题,有很多解决方案。以下是其中几种,包括使用Eclipse Collections容器提供的其他两个答案。

MutableList<MutableMap<String, MutableList<String>>> list =
        Lists.mutable.with(
                Maps.mutable.with(
                        "a", Lists.mutable.with("b", "c", "d"),
                        "b", Lists.mutable.with("a", "b")),
                Maps.mutable.with(
                        "c", Lists.mutable.with("a", "f")));

ImmutableSet<String> expected = Sets.immutable.with("a", "b", "c", "d", "f");

// Accepted Streams solution
Set<String> stringsStream = list.stream()
        .map(Map::values)
        .flatMap(Collection::stream)
        .flatMap(Collection::stream)
        .collect(Collectors.toSet());
Assert.assertEquals(expected, stringsStream);

// Lazy Eclipse Collections API solution
MutableSet<String> stringsLazy = list.asLazy()
        .flatCollect(MutableMap::values)
        .flatCollect(e -> e)
        .toSet();
Assert.assertEquals(expected, stringsLazy);

// Eager Eclipse Collections API solution
MutableSet<String> stringsEager =
        list.flatCollect(
                map -> map.flatCollect(e -> e),
                Sets.mutable.empty());
Assert.assertEquals(expected, stringsEager);

// Fused collect operation
Set<String> stringsCollect = list.stream()
        .collect(
                HashSet::new,
                (set, map) -> map.values().forEach(set::addAll),
                Set::addAll);
Assert.assertEquals(expected, stringsCollect);

// Fused injectInto operation
MutableSet<String> stringsInject =
        list.injectInto(
                Sets.mutable.empty(),
                (set, map) -> set.withAll(map.flatCollect(e -> e)));
Assert.assertEquals(expected, stringsInject);

注意:我是Eclipse Collections的提交者。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接