【问题标题】:How to copy a HashMap to an ArrayList with different references如何将 HashMap 复制到具有不同引用的 ArrayList
【发布时间】:2013-05-06 04:24:15
【问题描述】:

我在 Java 中对对象的引用有问题。这是情况。

假设我有一个名为 MyObject 的对象类。

class MyObject {
      Long id;
      String item;
      Integer number;
      BigDecimal bigNumber;
      //and Some getter and setter methods 
}

假设我有 hashmap:

HashMap<Long, MyObject> myHash = new HashMap<Long, MyObject>();

我用 MyObject 的一些对象填充这个 hashmap。

然后,当我尝试将此 hashmap 的所有元素复制到 arrayList(使用 addAll 方法)时,hashmap 中包含的所有对象都将复制到具有相同引用的 arraylist。出于这个原因,当我尝试在 hashmap 中更改 MyObject 对象时,它也在 arrayList 中更改。我不想那样。我该如何预防?

我希望我清楚地说明问题。

提前致谢。

【问题讨论】:

  • 您必须复制MyObject,通常使用复制构造函数。

标签: java object reference arraylist hashmap


【解决方案1】:

目前您只是在复制参考资料。这样做是因为复制对象非常昂贵。

在您的情况下,您想要复制对象,因此您需要在将它们添加到列表时复制每个对象。类似的东西

for(MyObject mo: myHash.values())
    list.add(mo.copy());

您可以通过多种方式实现复制,包括使用 clone();

【讨论】:

    【解决方案2】:

    我将通过实现Cloneable 接口使MyObject 类可克隆,请参阅Cloneable Javadoc

    Java 复制引用而不是对象。学习和理解这一点很重要。在您的情况下,您想要复制对象,因此您必须实现一个方法,该方法通过地图,复制您的对象,并将对这些副本的引用放入数组中。

    如果您需要更多关于 Java 克隆的信息,this Wikipedia page 是一个很好的来源。

    解决方案可能如下所示:

    • 通过实现Cloneable 接口使MyObject 类可克隆。 Object 具有方法 clone() 的默认实现,它复制所有字段。在您的情况下,您有 LongStringIntegerBigDecimal 字段。它们都是不可变的,所以它们不需要自己克隆,这就是为什么你不需要在你的类的 clone() 方法中做任何事情。您仍然需要覆盖 Object.clone() 才能将其公开。如果您的某个字段引用了另一个需要克隆的对象,则需要将代码添加到 clone()

      class MyObject implements Cloneable {
          Long id;
          String item;
          Integer number;
          BigDecimal bigNumber;
          //and Some getter and setter methods
      
          @Override
          public MyObject clone() throws CloneNotSupportedException {
              return (MyObject)super.clone();
          }
      }
      
    • 编写一个将地图中的对象复制到数组中的方法:

      public ArrayList<MyObject> getArray() {
          ArrayList<MyObject> list = new ArrayList<MyObject>(myHash.size());
      
          for(MyObject object : myHash)
              list.add(object.clone());
      }
      

    【讨论】:

      【解决方案3】:

      您应该创建数据的副本,然后将副本与列表一起使用:

      class MyObject { 
        ..
      
        public MyObject dupe() {
          return new MyObject(id, item, number, bigNumber, ..);
        }
      }
      
      void createList() {
        ArrayList<MyObject> list = new ArrayList<MyObject>();
        for (Map.Entry<Long, MyObject> e : map.entries())
          list.add(e.getValue().dupe());
      }
      

      【讨论】:

        【解决方案4】:

        在将 MyObject 添加到 arraylist 之前,您需要克隆/复制它们。当您使用 addAll 时,仅将对象引用从源集合复制到目标集合,而不是对象本身。

        ArrayList copyTo = new ArrayList()
        for( MyObject current : myHash.values() )
        {
           copyTo.add(copy(current));
        } 
        
        
        MyObject copy(MyObject o)
        {
          MyObject copyObj = new MyObject();
          // set attributes here from 'o' to 'copyObj'
          return copyObj;
        } 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-03-02
          • 2019-09-13
          • 2016-01-13
          • 1970-01-01
          • 1970-01-01
          • 2017-12-30
          • 1970-01-01
          相关资源
          最近更新 更多