【问题标题】:copy map to another new map将地图复制到另一个新地图
【发布时间】:2015-09-05 00:53:45
【问题描述】:

我有 2 个 HashMap 如下:

@Session
private Map< Integer, List< ObjectA >> keyMap;

@Session
private Map< Integer, List< ObjectA >> keyMap2;

一开始我会在keyMap里面放一些数据,然后我试着把keyMap里面的数据存到keyMap2里面:

keyMap2 = keyMap;

然后,我将在keyMap 中编辑一些数据。但是,keyMap2 中的值会随着我在keyMap 中的编辑而改变。

据我了解,这是因为keyMap2 仅指向keyMap 指针,所以keyMap 中的任何更改都会反映在keyMap2 中,因为相同的指针。 (如果我错了,请纠正我。)

我希望保留keyMap2 的值,而不需要像keyMap 这样的更改。除了我循环 keyMap 并将 1 比 1 放入 keyMap2 之外的任何想法。

【问题讨论】:

  • keyMap2 = new HashMap&lt;&gt;(keyMap).
  • 嗨@saka1029,这对我不起作用。我想可能是我的 HashMap 里面包含了一个列表。我并对keyMap的列表进行更改

标签: java pointers hashmap


【解决方案1】:
keyMap2 = new HashMap<Integer, List<ObjectA>>(keyMap);

将 HashMap 替换为您喜欢或需要的任何 Map 实现。

【讨论】:

    【解决方案2】:

    使用 Java 8 Stream 和方法参考:

     Map<Integer, List<ObjectA>> keyMap2 = keyMap.entrySet().stream()
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    

    或者,如果您想将 keyMap 中的列表也复制到另一个列表中,那么

    Map<Integer, List<ObjectA>> keyMap2 = keyMap.entrySet().stream()
                        .collect(Collectors.toMap(Map.Entry::getKey, e -> new ArrayList<ObjectA>(e.getValue())));
    

    【讨论】:

      【解决方案3】:

      您遇到的问题称为aliasing

      为了解决您的问题,您必须:

      • 在您的类ObjectA 上定义clone 方法
      • 遍历第一张地图的keySet,因此:
        • 获取与特定键关联的List 实例
        • 创建该列表的新实例
        • 迭代前者,克隆包含的元素并将它们放入后者中
        • 将新列表连同用于获取原始列表的键一起放入第二个映射中

      这样,您从头开始创建一个新列表和一整套元素,这些元素在内容方面与原始元素相同,但在内存中不是相同的对象。

      【讨论】:

      • 嗨,这对我不起作用。 keyMap2.clear( ); keyMap2.putAll( serviceAccountsKeyMap ); keyMap2 如果我更改 keyMap 中的值,则值仍然会更改@
      【解决方案4】:

      已编辑:如评论中所述,由于通过引用复制包含的列表,原始方法将不起作用。

      如果使用 Java8 流的方法不起作用,另一种可能性是使用以下方法迭代 Map:

      for (keyMap.Entry<Integer, List<ObjectA>> entry : map.entrySet()) {
          //Code
      }
      

      然后,您可以使用 entry.getKey() 将内容复制到 keyMap2 中,并从 entry.getValue() 复制 List 的浅拷贝或深拷贝

      如果只需要浅拷贝(通过引用复制 ObjectA)new ArrayList&lt;ObjectA&gt;(entry.getValue())应该可以工作,但对于深拷贝(需要 ObjectA 的新实例),则需要有关对象的更多信息。


      原文:

      您需要完整地复制哈希图。

      这包含在:copying a java hashmap

      本质上private Map&lt; Integer, List&lt; ObjectA &gt;&gt; keyMap2 = new HashMap&lt; Integer, List&lt; ObjectA &gt;&gt;(keyMap);

      或者keyMap2.addAll(keyMap);

      【讨论】:

      • 地图接口确实提供了putAll方法,不是吗?
      • 嗨,这对我不起作用。 keyMap2.clear( ); keyMap2.putAll( serviceAccountsKeyMap ); keyMap2 如果我更改 keyMap 中的值,则值仍然会更改@
      • 等一下,您是在更改 keyMap 的内容还是该映射包含的某个对象的属性?在后一种情况下,您仍然会遇到混叠问题...
      【解决方案5】:

      您可以像这样使用 Java 8 Stream 进行复制。

          Map<String, List<ObjectA>> keyMap2 = keyMap.entrySet().stream()
              .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), new ArrayList<>(e.getValue())))
              .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
      

      此代码复制keyMap 的值列表。

      【讨论】:

        【解决方案6】:

        在 Java 中没有指针之类的东西。使用(为此使用 C\C++),这样您的更改将不会反映。您可以使用:

        keyMap2 = (HashMap<String, String>) keyMap.clone();
        

        或者:

        keyMap.putAll(keyMap2) //This will add all the keys in "keymap" to "keymap2"
        //Source: http://docs.oracle.com/javase/7/docs/api/java/util/Map.html
        

        同样,更改不会反映,因为 Java 中没有 pointers

        干杯。

        【讨论】:

          【解决方案7】:

          正如您正确提到的,keyMap2 指向与keyMap 相同的 HashMap

          但如果你这样做:

          keyMap2 = (HashMap<String, String>) keyMap.clone();
          

          这将复制keyMap 并将keyMap2 指向该副本。对keyMap 的任何更改都不会反映在副本中

          这会解决你的问题

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-02-14
            • 1970-01-01
            • 2021-07-10
            • 2016-04-17
            • 1970-01-01
            • 1970-01-01
            • 2021-04-01
            相关资源
            最近更新 更多