Java 8 Streams 映射对象的浅拷贝,使用流交叉连接
Java 8 Streams Shallow copy of map object, cross join using streams
我的输入是:
List<Map<String, String>> = [{1=a, 2=b, 3=c},
{1=d, 2=e, 3=f}]
List<String> = [x, y, z]
预期输出为:
[
{1=a, 2=b, 3=c, 4=x},
{1=a, 2=b, 3=c, 4=y},
{1=a, 2=b, 3=c, 4=z},
{1=d, 2=e, 3=f, 4=x},
{1=d, 2=e, 3=f, 4=y},
{1=d, 2=e, 3=f, 4=z}
]
我的代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ExplodeData {
public static void main(String[] args) {
List<Map<String, String>> listOfMap = List.of(
new HashMap<>(Map.of("1", "a", "2", "b", "3", "c")),
new HashMap<>(Map.of("1", "d", "2", "e", "3", "f"))
);
List<String> stringList = new ArrayList<>();
stringList.add("x");
stringList.add("y");
stringList.add("z");
listOfMap.forEach(System.out::println);
System.out.println(stringList + "\n\n");
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, String> eachMap: listOfMap) {
for (String eachString: stringList) {
Map<String, String> newEntry = new HashMap<>();
newEntry.putAll(eachMap);
newEntry.put("4", eachString);
result.add(newEntry);
}
}
System.out.println("Expected Result using for loops");
result.forEach(System.out::println);
List<Map<String, String>> result2 = stringList
.stream()
.flatMap(each -> listOfMap.stream().peek(entry -> entry.put("4", each)))
.collect(Collectors.toList());
System.out.println("\n\nResult using streams");
result2.forEach(System.out::println);
}
}
问题:我想将给出正确结果的 for 循环转换为流。我当前的流代码给出了正确的结果大小,即 (listOfMap * stringList) 但由于浅拷贝,新键的值被覆盖。
当前输出
Expected Result using for loops
{1=a, 2=b, 3=c, 4=x}
{1=a, 2=b, 3=c, 4=y}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=x}
{1=d, 2=e, 3=f, 4=y}
{1=d, 2=e, 3=f, 4=z}
Result using streams
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=z}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=z}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=z}
感谢您的帮助。
您可以将 flatMap()
与生成 new 映射流的函数一起使用,就像循环版本所做的那样,并将所有内容收集回列表中。您的流版本修改现有地图 in-place,并不断用新元素覆盖以前添加的 "4"
元素。
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Demo {
public static void main(String[] args) {
List<Map<String, String>> listOfMap =
List.of(Map.of("1", "a", "2", "b", "3", "c"),
Map.of("1", "d", "2", "e", "3", "f"));
List<String> stringList = List.of("x", "y", "z");
List<Map<String, String>> result =
listOfMap.stream()
.flatMap(map -> stringList.stream().map(elem -> {
Map<String, String> newMap = new HashMap<>(map);
newMap.put("4", elem);
return newMap;
}))
.collect(Collectors.toList());
for (Map<String, String> elem : result) {
System.out.println(elem);
}
}
}
产出
{1=a, 2=b, 3=c, 4=x}
{1=a, 2=b, 3=c, 4=y}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=x}
{1=d, 2=e, 3=f, 4=y}
{1=d, 2=e, 3=f, 4=z}
这是避免使用 flatMap
的一种方法。
List<Map<String, String>> map =
List.of(Map.of("1", "a", "2", "b", "3", "c"),
Map.of("1", "d", "2", "e", "3", "f"));
List<String> list = List.of("x", "y", "z");
- 使用
mapmulti
创建新地图并使用新元素对其进行修改
- 然后将每个新地图放到流中
- 并收集到列表中。
List<Map<String, String>> newList = map.stream()
.<Map<String, String>>mapMulti((mp, consumer) -> {
for (String v : list) {
Map<String, String> newMap =
new HashMap<>(mp);
newMap.put("4", v);
consumer.accept(newMap);
}
}).toList();
for (Map<?,?> nmap : newList) {
System.out.println(nmap);
}
打印
{1=a, 2=b, 3=c, 4=x}
{1=a, 2=b, 3=c, 4=y}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=x}
{1=d, 2=e, 3=f, 4=y}
{1=d, 2=e, 3=f, 4=z}
mapMulti 是在 Java 16.
中引入的
我的输入是:
List<Map<String, String>> = [{1=a, 2=b, 3=c},
{1=d, 2=e, 3=f}]
List<String> = [x, y, z]
预期输出为:
[
{1=a, 2=b, 3=c, 4=x},
{1=a, 2=b, 3=c, 4=y},
{1=a, 2=b, 3=c, 4=z},
{1=d, 2=e, 3=f, 4=x},
{1=d, 2=e, 3=f, 4=y},
{1=d, 2=e, 3=f, 4=z}
]
我的代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ExplodeData {
public static void main(String[] args) {
List<Map<String, String>> listOfMap = List.of(
new HashMap<>(Map.of("1", "a", "2", "b", "3", "c")),
new HashMap<>(Map.of("1", "d", "2", "e", "3", "f"))
);
List<String> stringList = new ArrayList<>();
stringList.add("x");
stringList.add("y");
stringList.add("z");
listOfMap.forEach(System.out::println);
System.out.println(stringList + "\n\n");
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, String> eachMap: listOfMap) {
for (String eachString: stringList) {
Map<String, String> newEntry = new HashMap<>();
newEntry.putAll(eachMap);
newEntry.put("4", eachString);
result.add(newEntry);
}
}
System.out.println("Expected Result using for loops");
result.forEach(System.out::println);
List<Map<String, String>> result2 = stringList
.stream()
.flatMap(each -> listOfMap.stream().peek(entry -> entry.put("4", each)))
.collect(Collectors.toList());
System.out.println("\n\nResult using streams");
result2.forEach(System.out::println);
}
}
问题:我想将给出正确结果的 for 循环转换为流。我当前的流代码给出了正确的结果大小,即 (listOfMap * stringList) 但由于浅拷贝,新键的值被覆盖。
当前输出
Expected Result using for loops
{1=a, 2=b, 3=c, 4=x}
{1=a, 2=b, 3=c, 4=y}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=x}
{1=d, 2=e, 3=f, 4=y}
{1=d, 2=e, 3=f, 4=z}
Result using streams
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=z}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=z}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=z}
感谢您的帮助。
您可以将 flatMap()
与生成 new 映射流的函数一起使用,就像循环版本所做的那样,并将所有内容收集回列表中。您的流版本修改现有地图 in-place,并不断用新元素覆盖以前添加的 "4"
元素。
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Demo {
public static void main(String[] args) {
List<Map<String, String>> listOfMap =
List.of(Map.of("1", "a", "2", "b", "3", "c"),
Map.of("1", "d", "2", "e", "3", "f"));
List<String> stringList = List.of("x", "y", "z");
List<Map<String, String>> result =
listOfMap.stream()
.flatMap(map -> stringList.stream().map(elem -> {
Map<String, String> newMap = new HashMap<>(map);
newMap.put("4", elem);
return newMap;
}))
.collect(Collectors.toList());
for (Map<String, String> elem : result) {
System.out.println(elem);
}
}
}
产出
{1=a, 2=b, 3=c, 4=x}
{1=a, 2=b, 3=c, 4=y}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=x}
{1=d, 2=e, 3=f, 4=y}
{1=d, 2=e, 3=f, 4=z}
这是避免使用 flatMap
的一种方法。
List<Map<String, String>> map =
List.of(Map.of("1", "a", "2", "b", "3", "c"),
Map.of("1", "d", "2", "e", "3", "f"));
List<String> list = List.of("x", "y", "z");
- 使用
mapmulti
创建新地图并使用新元素对其进行修改 - 然后将每个新地图放到流中
- 并收集到列表中。
List<Map<String, String>> newList = map.stream()
.<Map<String, String>>mapMulti((mp, consumer) -> {
for (String v : list) {
Map<String, String> newMap =
new HashMap<>(mp);
newMap.put("4", v);
consumer.accept(newMap);
}
}).toList();
for (Map<?,?> nmap : newList) {
System.out.println(nmap);
}
打印
{1=a, 2=b, 3=c, 4=x}
{1=a, 2=b, 3=c, 4=y}
{1=a, 2=b, 3=c, 4=z}
{1=d, 2=e, 3=f, 4=x}
{1=d, 2=e, 3=f, 4=y}
{1=d, 2=e, 3=f, 4=z}
mapMulti 是在 Java 16.
中引入的