当前位置: 首页 > 知识库问答 >
问题:

在Java8中用嵌套数据结构实现映射的功能倒置

刘兴修
2023-03-14

我有一个问题现在快把我逼疯了。我试图避免为这个映射反转创建一个中间对象。(目标:我有一个带有嵌套数据结构的映射,我想对其进行反转和爆炸。所以,

Map<Foo,Set<String>> fooStringMap

变成

Map<String,Foo> expandedStringFooMap

//Inverting a map is simple
private <X,Y> Map<Y,X> invertMap(Map<X,Y> source){
    return source.entrySet().stream()
                            .collect(Collectors.toMap(Entry::getValue,Entry::getKey)

private <A,B> Map<A,B> explodeMapWithCollection(Map<? extends Collection<A>, B> collectionMap){
 collectionMap.entrySet().stream()
            .flatMap(x -> x.getKey().stream().collect(Collectors.toMap(Function.identity(),x.getValue())))
            .collect(Collectors.toMap(Entry::getKey,Entry::getValue));
}

目前,这不起作用。我甚至不认为上面会编译,所以就当它是伪代码吧。

someMap.keySet().stream().flatMap(key->someMap.get(key).stream().map(val -> new 
Pair<>(val,key))).collect(Collectors.toMap(Pair::getLeft,Pair::getRight)));

共有1个答案

濮阳振
2023-03-14

下面是一种在条目集上使用自定义流#collect的方法。有人可能会争辩说,由于隐藏在累加器中的foreach,这并不是“完全有效的”,但是在某些时候,必须创建映射条目,我不确定是否有一种“优雅的”方法来使用set的流(条目值),并且仍然有可能访问条目键(它将成为新条目的值)。

一个附带说明(尽管我拿起棍棒进行过程性编程,冒着被否决的风险):您不必仅仅因为可以就用函数式的方式来完成它。当你说你“迷失在语法中”,那么

  1. 几周后再次阅读此代码时,您会怎么想?
  2. 当你的同事第一次读这段代码时会怎么想?(我担心的是那个带着电锯和守门员面具的...)
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapInvert
{
    public static void main(String[] args)
    {
        Map<Integer, Set<String>> map = 
            new LinkedHashMap<Integer, Set<String>>();

        map.put(1, new LinkedHashSet<String>(Arrays.asList("A","B","C")));
        map.put(2, new LinkedHashSet<String>(Arrays.asList("D","E","F")));
        map.put(3, new LinkedHashSet<String>(Arrays.asList("G","H","I")));

        Map<String, Integer> resultA = inverseEx(map);
        System.out.println("Procedural: "+resultA);

        Map<String, Integer> resultB = map.entrySet().stream().collect(
            LinkedHashMap::new, 
            (m, e) -> e.getValue().forEach(v -> m.put(v, e.getKey())), 
            (m0, m1) -> m0.putAll(m1));
        System.out.println("Functional: "+resultB);
    }

    /**
     * Invert the given map, by mapping each element of the values to
     * the respective key
     *  
     * @param map The input map
     * @return The inverted map
     */
    private static <K, V> Map<V, K> inverseEx(
        Map<K, ? extends Collection<? extends V>> map)
    {
        Map<V, K> result = new LinkedHashMap<V, K>();
        for (Entry<K, ? extends Collection<? extends V>> e : map.entrySet())
        {
            for (V v : e.getValue())
            {
                result.put(v, e.getKey());
            }
        }
        return result;
    }
}
 类似资料:
  • 如何使用MapStruct映射嵌套列表? 下面是我的实体类: 我想把它映射到: 现在,我的映射器看起来像: 但它只映射“普通”属性,如Long、intger等,但它避免了嵌套列表。

  • 想要将每个数字乘以3,如下所示 为什么会导致以下异常?我如何才能真正访问地图?

  • 当尝试使用@Data和@Builder映射嵌套对象时,mapStruct会抛出以下错误:“在目标类型中找不到属性“profile”的读取访问器。” 为简单起见,使用Lombok简化模型 前两个映射按预期工作,但当尝试将两者结合起来时,会在编译时引发以下错误“在目标类型中的属性“配置文件”中找不到读取访问器。” 如果有人能在这件事上帮我,我会非常感激。 谢谢, 乔纳森。

  • 我需要在这里显示json响应

  • 我需要展平一个数据帧,以便将其与Spark(Scala)中的另一个数据帧连接起来。 基本上,我的2个数据帧有以下模式: 数据流1 DF2 老实说,我不知道如何使DF2变平。最后,我需要连接DF.field4 = DF2.field9上的2个数据帧 我用的是2.1.0 我的第一个想法是使用爆炸,但在Spark 2.1.0中已经被否决了,有人能给我一点提示吗?

  • 我用的是Protobuf 3。从文档来看,似乎无法定义嵌套贴图: 我正在尝试创建一种消息类型来表示期权链的定价信息(出价和要价)。对于那些不熟悉这些金融工具的人,基本上我有一套“到期日期(YYYYMMDD)”。在每个过期日期中,我都有一组“strikes(float number;如果需要,可以用字符串表示,我同意)”。在每次行使中,我有两个期权,一个“看跌”和一个“看涨”(这被称为期权的“右”)