others - Java - 如何将Stream<Map<String, Map<String, String>>>合并为单个 Map<String, Map<String, String>>?

135 0

我正在尝试合并一个 Stream<Map<String, Map<String, String>>>对象在所有Streams中使用key的单个映射。

例如,


final Map<String, someOtherObjectToProcess> someObject;



final List<Map<String, Map<String, String>>> list = someObject.entrySet()


 .stream()


 .flatMap(this::getInfoStream)


 .collect(Collectors.toList());



getInfoStream的签名为


public Stream<Map<String, Map<String, String>>> getInfoStream(Map.Entry<String, someOtherObjectToProcess> entry)



如果我使用(Collectors.toList()),我就可以得到这些Map对象的列表。

如果使用上面的代码,则例子输出:


[{


"name" : {


"property":"value"


 }


},



{


"name2" : {


"property":"value"


 }


}]



但我想collect Map的结构


{


"name" : {


"property":"value"


 },


"name2" : {


"property":"value"


 }


}



如何使用Collectors.toMap()或其他替代方法进行这个操作?

时间: 原作者:

78 0

当你有


Stream<Map<String, Map<String, String>>> stream = ...



(我假设是.flatMap(this::getInfoStream)的结果)你可以调用


.flatMap(map -> map.entrySet().stream())



创建要生成的所有map的步骤 Stream<Map.Entry<String, Map<String, String>>>

假设每个键在你可以使用的所有map上都是唯一


.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));



但是如果键不是唯一的,你需要决定应该在新映射中放置什么值以获得相同的键。 我们可以通过填充...部件来完成


.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (vOld, vNew) -> ...));


// ^^^



其中vOld保存在结果映射中当前保存的值,而vNew保存新的值(从当前流"迭代"),
(vOld, vNew) -> vOld

简单而言,(假定唯一key):


Map<String, Map<String, String>> combinedMap = 


 /*your Stream<Map<String, Map<String, String>>>*/


 .flatMap(map -> map.entrySet().stream())


 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));



原作者:
94 1

解决此问题的另一种方法是不使用collector(toList()),而是使用Supplier ,accumulator 和Combiner的重载.collect()方法:


Stream<Map<String, Map<String, String>>> stream = ...


Map<String, Map<String, String>> result = stream


 .collect(HashMap::new, HashMap::putAll, HashMap::putAll);



原作者:
66 1

我认为最容易的方法是将所有内容映射到Map.Entry然后使用Collectors::toMap将所有内容收集回Map


import static java.util.stream.Collectors.toMap;



// ...



someObject.entrySet()


 .stream()


 .flatMap(this::getInfoStream)


 .flatMap(map -> map.entrySet().stream())


 .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (one, two) -> one));



(one, two) -> one

原作者:
133 0

你可以使用reduce来组合 Map<String, Map<String, String>>元素变成一个:


import java.util.HashMap;


import java.util.Map;


import java.util.stream.Stream;



public class Main {



 public static void main(String[] args) {


 alternative1();


 alternative2();


 }



 // Use reduce without an initial identity value


 public static void alternative1() {


 Map<String, Map<String, String>> m1 = new HashMap<>();


 m1.put("name", Map.of("property","value"));



 Map<String, Map<String, String>> m2 = new HashMap<>();


 m2.put("name2", Map.of("property","value"));



 Stream<Map<String, Map<String, String>>> mapStream = Stream.of(m1, m2);



 Map<String, Map<String, String>> m3 = mapStream.reduce((a, b) -> {


 Map<String, Map<String, String>> temp = new HashMap<>();


 temp.putAll(a);


 temp.putAll(b);


 return temp;


 }).orElseThrow();



 System.out.println(m3);


 }



 // Use reduce with an initial empty map as the identity value


 public static void alternative2() {


 Map<String, Map<String, String>> m1 = new HashMap<>();


 m1.put("name", Map.of("property","value"));



 Map<String, Map<String, String>> m2 = new HashMap<>();


 m2.put("name2", Map.of("property","value"));



 Stream<Map<String, Map<String, String>>> mapStream = Stream.of(m1, m2);



 Map<String, Map<String, String>> m3 = mapStream.reduce(new HashMap<>(), (a, b) -> {


 a.putAll(b);


 return a;


 });



 System.out.println(m3);


 }


}




输出:


{name={property=value}, name2={property=value}}


{name={property=value}, name2={property=value}}



但是要注意,这些解决方案假定(namename2 )是唯一的,否则重复的键将使映射条目相互覆盖。

更现代的语法,逻辑相同:


import java.util.HashMap;


import java.util.Map;


import java.util.stream.Stream;



public class Main {



 public static void main(String[] args) {


 alternative1();


 alternative2();


 }



 // Use reduce without an initial identity value


 public static void alternative1() {


 var m1 = Map.of("name", Map.of("property","value"));


 var m2 = Map.of("name2", Map.of("property","value"));


 var m3 = Stream.of(m1, m2).reduce((a, b) -> {


 var temp = new HashMap<String, Map<String, String>>();


 temp.putAll(a);


 temp.putAll(b);


 return temp;


 }).orElseThrow();



 System.out.println(m3);


 }



 // Use reduce with an initial empty map as the identity value


 public static void alternative2() {


 var m1 = Map.of("name", Map.of("property","value"));


 var m2 = Map.of("name2", Map.of("property","value"));


 var m3 = Stream.of(m1, m2).reduce(new HashMap<>(), (a, b) -> {


 a.putAll(b);


 return a;


 });



 System.out.println(m3);


 }


}



原作者:
...