在给定函数和一组参数的情况下,是否有一种简单的方法来创建反向映射?

时间:2015-01-06 14:12:58

标签: java java-8

假设我们有一个将X映射到Y的纯方法:

public abstract Y map(X x);

是否有任何简短的方法可以创建从函数到映射到这些函数的参数集的反向映射?也就是说,要从Map<Y, Set<X>>创建Set<X>。简而言之,我指的是比直接方式更简洁的库解决方案:

public Map<Y, Set<X>> reverseMapping(Set<X> arguments) {
    Map<Y, Set<X>> answer = new HashMap<>();
    arguments.forEach(x->{
        Y y = map(x);
        if (!answer.containsKey(y)) {
            answer.put(y, new HashSet<>());
        }
        answer.get(y).put(x);
    });
    return answer;
}

Java 8中添加了许多函数式编程功能,我认为可能是我需要的功能。

2 个答案:

答案 0 :(得分:3)

这种任务有一个直接的解决方案,Collectors.groupingBy。虽然单参数版本生成Map<Y,List<X>,但您可combine it with another Collector生成Set s

public Map<Y, Set<X>> reverseMapping(Set<X> arguments) {
    return arguments.stream()
        .collect(Collectors.groupingBy(this::map, Collectors.toSet()));
}
public abstract Y map(X x);

答案 1 :(得分:0)

您也可以随时提供Function作为参数,然后编程模型就会很好。

public <X, Y> Map<Y, Set<X>> reverseMapping(Set<X> arguments, Function<X, Y> fn) {
    return arguments.stream()
            .collect(
                    Collectors.groupingBy(
                            fn, // The "map" invocation
                            Collectors.toSet()));
}

@Test
public void testFn() {
    final Set<String> cities = 
        Stream.of("NYC", "Los Angeles", "San Fransisco")
              .collect(Collectors.toSet());

    final Map<String, Set<String>> reversed = 
        reverseMapping(cities, city -> mapState(city));

    System.out.println(reversed); // -> {NY=[NYC], California=[San Fransisco, Los Angeles]}

}

// This is one version of a "map"-method as provided by the OP
private String mapState(String city) {
    switch (city) {
        case "NYC":
            return "NY";
        case "Los Angeles":
        case "San Fransisco":
            return "California";
    }
    return "Unknown";
}

基本上,您可以将自己的地图 - 方法作为lambda提供。