我有这些模型类:
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表达式转换此代码呢?
答案 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;
}
}