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.

中引入的