Java 8使用Collectors.toMap连接映射
我试图在一个映射中收集进程的结果,一个对象列表,它返回一个映射。我想我应该和一个收藏家一起做。但是我还没有找到方法 代码如下:Java 8使用Collectors.toMap连接映射,java,java-8,java-stream,collectors,Java,Java 8,Java Stream,Collectors,我试图在一个映射中收集进程的结果,一个对象列表,它返回一个映射。我想我应该和一个收藏家一起做。但是我还没有找到方法 代码如下: public class Car { List<VersionCar> versions; public List<VersionCar> getVersions() { return versions; } } public class VersionCar { private Stri
public class Car {
List<VersionCar> versions;
public List<VersionCar> getVersions() {
return versions;
}
}
public class VersionCar {
private String wheelsKey;
private String engineKey;
public String getWheelsKey() {
return wheelsKey;
}
public String getEngineKey() {
return engineKey;
}
}
公车{
列出版本;
公共列表getVersions(){
返回版本;
}
}
公共类VersionCar{
私人弦轮;
私有字符串引擎;
公共字符串getWheelsKey(){
返回轮;
}
公共字符串getEngineKey(){
返回引擎键;
}
}
处理方法:
private static Map<String,Set<String>> processObjects(VersionCar version) {
Map<String,Set<String>> mapItems = new HashMap<>();
mapItems.put("engine", new HashSet<>(Arrays.asList(version.getEngineKey())));
mapItems.put("wheels", new HashSet<>(Arrays.asList(version.getWheelsKey())));
return mapItems;
}
private静态映射processObjects(VersionCar版本){
Map mapItems=新的HashMap();
mapItems.put(“引擎”,新的哈希集(Arrays.asList(version.getEngineKey()));
mapItems.put(“wheels”,新哈希集(Arrays.asList(version.getWheelsKey()));
返回mapItems;
}
我的最终代码是:
Map<String,Set<String>> mapAllItems =
car.getVersions().stream()
.map(versionCar -> processObjects(versionCar))
.collect(Collectors.toMap()); // here I don't know like collect the map.
地图项目=
car.getVersions().stream()
.map(versionCar->processObjects(versionCar))
.collect(Collectors.toMap());//这里我不知道我喜欢收集地图。
我的想法是处理版本列表,最后得到一个包含两个项目的地图:轮子和引擎,但是有一个包含所有版本的所有不同项目的集合。你有什么想法,我可以用Collectors.toMap或其他选项来实现吗 您可以使用收集器.toMap(键映射器、值映射器、合并函数)。最后一个参数用于解决与同一键关联的值之间的冲突 例如:
Map<String, Set<String>> mapAllItems =
car.getVersions().stream()
.map(versionCar -> processObjects(versionCar))
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(firstSet, secondSet) -> {
Set<String> result = new HashSet<>();
result.addAll(firstSet);
result.addAll(secondSet);
return result;
}
));
地图项目=
car.getVersions().stream()
.map(versionCar->processObjects(versionCar))
.flatMap(m->m.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,
(第一套,第二套)->{
Set result=new HashSet();
结果:addAll(第一组);
结果:addAll(第二组);
返回结果;
}
));
在这种情况下,您想要使用的运算符可能是“reduce”
car.getVersions().stream()
.map(versionCar->processObjects(versionCar))
.减少((map1,map2)->{
map2.forEach((键,子集)->map1.get(键).addAll(子集));
返回map1;
})
.orElse(新HashMap());
“reduce”中使用的lambda是一个二进制运算符,它合并2个映射并返回合并的映射
“orElse”只是在您的初始集合(版本)为空的情况下返回一些内容。
从类型的角度来看,为了获得
mapAllItems
,它去掉了“可选的”,我们不需要也不应该定义processObjects
方法:
Map<String, Set<String>> mapAllItems = new HashMap<>();
mapAllItems.put("engine", car.getVersions().stream().map(v -> v.getEngineKey()).collect(Collectors.toSet()));
mapAllItems.put("wheels", car.getVersions().stream().map(v -> v.getWheelsKey()).collect(Collectors.toSet()));
将
.map(…)
更改为.flatMap(versionCar->processObjects(versionCar).entrySet().stream())
,然后使用收集器.groupingBy(Entry::getKey,…)
。需要多一点,但这会让你找到正确的方向。谢谢Andreas,这对找到方法是一个很大的帮助。谢谢你的帮助Vlad,我一直在寻找。你可以使用lambda作为二进制运算符,而不是匿名内部类,它在IMO:(s1,s2)->{s1.addAll(s2);返回s1;
。这需要将值映射器函数更改为e->newhashset(e.getValue())
,以便在实际需要时不改变原始集。此外,我不认为需要在这里使用flatMap
。只需使用processObjects
返回的映射即可。当然,我知道lambdas),但要小心s1.addAll(…),因为可以将不可变集设置为参数之一,这比我选择的答案要干净得多!与本例无关,但当map1
不包含key
时,此代码将抛出NPE。同意,但正如您提到的,在本例中不可能。请记住,在map1中可能有NPE,我添加了此map2.forEach((key,subset)->{if(map1.get(key)!=null){map1.get(key).addAll(subset);}else{map1.put(key,subset);}});如果map2的键数实际上比map1的多,因为键在每个映射“引擎”和“轮子”因为它们是由processObjects生成的,所以NPE不应该发生。但当然,最好是安全的。
Map<String, Set<String>> mapAllItems = new HashMap<>();
mapAllItems.put("engine", car.getVersions().stream().map(v -> v.getEngineKey()).collect(Collectors.toSet()));
mapAllItems.put("wheels", car.getVersions().stream().map(v -> v.getWheelsKey()).collect(Collectors.toSet()));
mapAllItems = car.getVersions().stream()
.flatMap(v -> Stream.of(new SimpleEntry<>("engine", v.getEngineKey()), new SimpleEntry<>("wheels", v.getWheelsKey())))
.collect(Collectors.groupingBy(e -> e.getKey(), Collectors.mapping(e -> e.getValue(), Collectors.toSet())));