使用流Java 8在Map <k,v>中转换List <v>

时间:2017-07-09 14:32:42

标签: java

我有这些模型类:

public class Student extends Person;

public class Professor extends Person;

public class University {
    private long id;
    private String name;
    private List<Person> employers;
....
}

我有一份大学名单,我想把它转换为地图; Person是一个抽象类,并实现了hashCode和equals方法。 这是一个带迭代的实现:

Map<Person, University> mapList = new HashMap<Person, University>();
for (University u : universities) {
    for (Person p : u.getEmployers()) {
       mapList.put(p,u);
    }
}
mapList.forEach((k,v) -> System.out.println(k.toString() + v.getName()));

我对Java 8流不太熟悉,但如何用lambda表达式转换此代码呢?

3 个答案:

答案 0 :(得分:2)

其他答案可能与您的Java 7版本完全相同,在这种情况下使用内置流的内容,使用forEach方法可能更简洁,但我想展示如何使用纯粹的FP风格操作,以便您可以通过流扩展您的舒适度。

你可以使用lambdas,但是你不需要为大多数函数使用方法引用:

universities.stream()
// create maps for each university
    .map(u -> u.getEmployer().stream()
                .collect(Collectors.toMap(Function.identity(), p -> u))
// You need the entry set to turn back into a stream
    .map(Map::entrySet)
// flatten the entry sets into a single stream
    .flatMap(Set::stream)
// finally collect into the final map
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))

如果您有一个带有元组的库,可以简化这一点,因为您可以跳过中间映射。您也可以使用Map.Entry的内置实现,但我发现它们太冗长而不值得。

如果静态导入诸如toMap,toList等的东西,

Streams可以更干净,更易读。

答案 1 :(得分:0)

我会这样做:

universities.stream().forEach((uni) -> uni.getEmployers().stream().forEach((p) -> mapList.put(p, uni)));

答案 2 :(得分:0)

我可能不是最好的解决方案,所以我会坚持使用java 7方法。但这是我的Stream API解决方案

    Map<Person, University> mapList = universities.stream()
            .flatMap(university -> university.getEmployers().stream()
                    .map(employer -> new Tuple<>(employer, university)))
            .collect(Collectors.toMap(Tuple::getV1, Tuple::getV2));

你还需要这种方法某种持有者类

class Tuple<T, V> {
    private final T v1;
    private final V v2;

    public Tuple(T v1, V v2) {
        this.v1 = v1;
        this.v2 = v2;
    }

    public T getV1() {
        return v1;
    }

    public V getV2() {
        return v2;
    }
}