【问题标题】:How to subtract two Maps in Java?如何在Java中减去两个地图?
【发布时间】:2013-11-20 08:55:00
【问题描述】:

我有两个成对的 Maps Collection,比如说, 将值视为整数列表。 即对于 Map1,key=1,values =array list with (2,3)

Map1       Map2
<1,2>      <1,2>
<1,3>      <1,4>
<2,4>      <2,5>
<2,5>      <2,6>

现在我想要 Map1-Map2 的结果:

<1,3>
<2,5>

或 Map2-Map1:

<1,4>
<2,6>

ArrayLists for Maps 中是否有类似 RemoveAll 的方法?另外,哪个 Map(SortedMap?) 是实现这一目标的最佳方式?

我是初学者如果你能引导我朝着正确的方向而不是投反对票,那就太好了。

【问题讨论】:

  • 首先,一个地图不能有两个具有相同键的条目。
  • .entrySet().removeAll()?
  • @R.J 如果我有值列表,成对,我的意思是?
  • 地图不能有重复的键。否则,您可以遍历 Map1 的条目并从 Map2 中逐个删除条目。如果你想比较值也把它放在一个 if 条件中

标签: java map


【解决方案1】:

这是在 google 提供的 Guava 库中。有一个名为entriesOnlyOnLeft() 的方法允许您提供两个映射并在查询左侧显示映射中的唯一条目。图书馆链接here

【讨论】:

    【解决方案2】:

    现在很明显,您想要一对 Set,解决方案相当简单。首先,您必须决定要使用什么配对类,例如AbstractMap.SimpleEntry 或自定义编写。如果是自定义 Pair 类,您必须确保具有正确的 equalshashCode 方法实现。但是自定义Pair 类的优点是您可以提供一个toString 方法返回正确的对表示,而Entry 实现在使用作为对时具有不正确的String 表示。因此,在我的示例中,我添加了自定义 SetString 的转换方法。

    → 使用Sets,您可以按照您的要求简单地使用removeAll

    public static void main(String[] args) throws InterruptedException
    {
      Set<Map.Entry<Integer,Integer>> set1=new HashSet<>(), set2=new HashSet<>();
      put(set1, 1, 2);
      put(set1, 1, 3);
      put(set1, 2, 4);
      put(set1, 2, 5);
    
      put(set2, 1, 2);
      put(set2, 1, 4);
      put(set2, 2, 5);
      put(set2, 2, 6);
    
      System.out.println("Set1: "+printAsTuple(set1));
      System.out.println("Set2: "+printAsTuple(set2));
      Set<Map.Entry<Integer,Integer>> uniqueSet1=new HashSet<>(set1);
      uniqueSet1.removeAll(set2);
      System.out.println("Unique in Set1: "+printAsTuple(uniqueSet1));
      Set<Map.Entry<Integer,Integer>> uniqueSet2=new HashSet<>(set2);
      uniqueSet2.removeAll(set1);
      System.out.println("Unique in Set2: "+printAsTuple(uniqueSet2));
    }
    
    private static <A,B> void put(Set<Map.Entry<A,B>> set1, A a, B b)
    {
      set1.add(new AbstractMap.SimpleEntry<>(a, b));
    }
    
    private static String printAsTuple(Set<Map.Entry<Integer, Integer>> set)
    {
      if(set.isEmpty()) return "[]";
      StringBuilder sb=new StringBuilder().append("[ ");
      for(Map.Entry<Integer, Integer> e:set)
        sb.append('<').append(e.getKey()).append(",").append(e.getValue()).append(">, ");
      sb.setLength(sb.length()-2);
      return sb.append(" ]").toString();
    }
    

    【讨论】:

      【解决方案3】:

      首先你必须在Java中了解Map。您不能有重复的keys。如果你用相同的键放置新的entry,以前的值将被替换。密钥必须是唯一的。

      所以你的问题是无效的。

       Map1       Map2
      <1,2>      <1,2>
      <1,3>      <1,4>
      <2,4>      <2,5>
      <2,5>      <2,6>
      

      考虑您的情况,最终地图将如下所示。相同键的先前值将替换为新值。

       Map1       Map2
       <1,3>     <1,4>
       <2,5>     <2,6>
      

      您可以执行以下操作

          Map<Integer,Integer> map1=new HashMap<>();
          Map<Integer,Integer> map2=new HashMap<>();
          map1.put(1,2);
          map1.put(2,3);
          map1.put(3,4);
      
          map2.put(1,2);
          map2.put(2,2);
          map2.put(3,2);
      
          for(Map.Entry<Integer,Integer> entry:map2.entrySet()){
              if(entry.getValue().equals(map1.get(entry.getKey()))){
                  map1.remove(entry.getKey());
              }
          }
          System.out.println(map1);
      

      【讨论】:

      • 我说如果我有一个键的值列表。那案子呢?
      • @David 然后遍历地图并删除与您的参考地图相关的公共元素。
      • 所以对于 Map1 中的每个键,我可以在值列表中使用 ArrayListForKeyInMap1.RemoveAll(ArrayListForKeyInMap2) ?
      • @Ruchira:你应该永远使用==比较Integer实例。它在某些情况下可能会起作用,尤其是对于较小的值,但它可能会在其他情况下中断。但无论如何,我不明白你循环的目的。为什么不用map1.entrySet().removeAll(map2.entrySet())
      猜你喜欢
      • 2017-03-05
      • 1970-01-01
      • 2011-07-03
      • 2011-03-31
      • 2011-05-21
      • 1970-01-01
      • 2012-10-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多