在嵌套数据结构上使用Java8流创建映射

时间:2014-11-10 16:40:58

标签: java map java-8 nested-loops java-stream

我正在使用Java 8的流搜索这段代码的优雅等价物:

Collection<X> xs = ...;
Map<B, A> map = new SomeMap<>();

for (X x : xs) {
    A a = x.getA();
    Collection<B> bs = x.getBs();

    for (B b : bs)
        map.put(b, a);
}

对我来说这个有点太棘手,因为我无法想到使用flatMap和Collectors.toMap来实现所需功能的组合。

可编辑的例子:

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class Application {

    public static class A {}

    public static class B {}

    public static class X {
        private A a;
        private Collection<B> bs;

        public X(A a, Collection<B> bs) {
            this.a = a;
            this.bs = bs;
        }

        public A getA() {
            return a;
        }

        public Collection<B> getBs() {
            return bs;
        }
    }

    public static void main(String[] args) {
        X x1 = new X(new A(), Arrays.asList(new B(), new B()));
        X x2 = new X(new A(), Arrays.asList(new B()));

        Collection<X> xs = Arrays.asList(x1, x2);

        Map<B, A> map = new HashMap<>();

        for (X x : xs) {
            A a = x.getA();
            Collection<B> bs = x.getBs();

            for (B b : bs)
                map.put(b, a);
        }
    }

}

1 个答案:

答案 0 :(得分:5)

您认为可以使用flatMap和toMap的混合物来实现:

Map<B, A> map = xs.stream()
                  .flatMap(x -> x.getBs().stream()
                                 .map(b -> new SimpleEntry<> (b, x.getA())))
                  .collect(toMap(Entry::getKey, Entry::getValue));

请注意,如果存在重复的B,此代码与原始代码不同:您的代码将覆盖相应的值,而此代码将引发异常。