> 进入列表> 并获得笛卡尔积?,java,list,dictionary,java-stream,cartesian-product"/>

首页 > 解决方案 > 如何转换地图> 进入列表> 并获得笛卡尔积?

问题描述

使用 Java 我正在尝试创建包含String键和List<String>值的地图的笛卡尔积。创建列表时,我需要保留键的值,如下所示:

我还要求当List<String>原始映射中的值为空时,在创建笛卡尔积时仍应将其视为单个值,以避免乘以 0 并且不创建映射。例如下面的地图:

{
    "Location Number" = {"100", "500"}
    "Department Number" = {"11", "22", "33"}
    "District Number" = {}
    "Preferred Language" = {"en-US"}
}

被翻译成:

{
    {
        "Location Number" = "100"
        "Department Number" = "11"
        "District Number" = {}
        "Preferred Language" = "en-US"
    },
    {
        "Location Number" = "100"
        "Department Number" = "22"
        "District Number" = {}
        "Preferred Language" = "en-US"
    },
    {
        "Location Number" = "100"
        "Department Number" = "33"
        "District Number" = {}
        "Preferred Language" = "en-US"
    },
    {
        "Location Number" = "500"
        "Department Number" = "11"
        "District Number" = {}
        "Preferred Language" = "en-US"
    },
    {
        "Location Number" = "500"
        "Department Number" = "22"
        "District Number" = {}
        "Preferred Language" = "en-US"
    },
    {
        "Location Number" = "500"
        "Department Number" = "33"
        "District Number" = {}
        "Preferred Language" = "en-US"
    }
}

下面是我目前用来完成类似翻译的代码,但它没有保留我需要的密钥。我不知道这是否可以在一般情况下使用 Java 8 Streams 来完成。

private static List<List<String>> createRuleListFromMap(Map<String, List<String>> ruleMap) {
    List<List<String>> ruleList = new ArrayList<>();
    cartesianProduct(ruleMap.values()).forEach(ruleList::add);
    return ruleList;
}

private static <T> Stream<List<T>> cartesianProduct(Collection<? extends Collection<T>> collections) {
    return cartesianProduct(new ArrayList<Collection<T>>(collections), Collections.emptyList());
}

private static <T> Stream<List<T>> cartesianProduct(List<? extends Collection<T>> collections, List<T> current) {
    return collections.isEmpty() ? Stream.of(current) : collections.get(0).stream().flatMap(e -> {
        List<T> list = new ArrayList<>(current);
        list.add(e);
        return cartesianProduct(collections.subList(1, collections.size()), list);
    });
}

标签: javalistdictionaryjava-streamcartesian-product

解决方案


这是如何转换为的简单Map<String,List<String>>示例List<Map<String,String>>

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class StreamTest {
    @Test
    public void test() {
        var map = new HashMap<String, List<String>>();
        map.put("key1", Arrays.asList("value1", "value2", "value3"));
        map.put("key2", Arrays.asList("value4", "value5", "value6"));

        var list = map.entrySet().stream()
                .flatMap(e -> e.getValue().stream()
                        .map(v -> Map.of(e.getKey(), v)))
                .collect(Collectors.toList());

        log.info(list.toString());
    }
}

推荐阅读