7 Replies Latest reply: Jun 3, 2011 12:33 AM by 866364 RSS

    Deep Copy of a List

    aksarben
      I'm trying to deep-copy a list, but my code won't compile:
      public static <T extends Cloneable> List<T> copy(final List<T> list) {
      
         final ArrayList<T> result = new ArrayList<T>();
            for (final T entry : list) {
               result.add((T)entry.clone());
            }
         return result;
      }
      The error message says The method clone() from the type Object is not visible. What do I need to change to make this work?
        • 1. Re: Deep Copy of a List
          DrClap
          Your T class has to have a public clone() method. All the compiler knows is that it implements Cloneable, which doesn't have any such method. So T would have to extend some class (or interface, I suppose) which had a public clone() method.
          • 2. Re: Deep Copy of a List
            aksarben
            Yeah, after doing a lot of Googling & head scratching I finally realized (as many others have before me) that the Cloneable interface suffers from an unfortunate design. Not only does it not have a clone() method itself (go figure), but Object.clone() is protected. In short, you can't do a efficient deep list copy generically. In case anyone is interested, the workaround I came up with is to add a static helper method to the classes whose lists I want to clone. For example, if MyClass implements Cloneable, I added this method to MyClass:
            public static List<MyClass> cloneList(final List<MyClass> list) {
               final ArrayList<MyClass> result = new ArrayList<MyClass>(list.size());
               for (final MyClass entry : list) {
                  result.add(entry.clone());
               }
               return result;
            }
            A pain in the a** to have to do this for each class, but at least it works, and the code to call it is compact:
            List<MyClass> original = new ArrayList<MyClass>();
            ...
            List<MyClass> copy = MyClass.cloneList(original);
            Life is so unfair...
            • 3. Re: Deep Copy of a List
              jtahlborn
              unfortunately, it is difficult to write a generic clone method in java due to the way cloning was designed. i believe that apache commons has some utils (CopyUtils?) which handle this (reflection is just about the only way to do it in a completely generic fashion).
              • 4. Re: Deep Copy of a List
                800268
                aksarben wrote:
                In short, you can't do a efficient deep list copy generically. In case anyone is interested, the workaround I came up with is to add a static helper method to the classes whose lists I want to clone. For example, if MyClass implements Cloneable, I added this method to MyClass:
                It's seems much simpler to let you class implement an interface PublicClonable as DrClap suggested and have a method:
                public static <T extends PublicCloneable> List<T> copy(final List<T> list) { .. }
                • 5. Re: Deep Copy of a List
                  aksarben
                  Actually, I don't think it is. In your example, the PublicCloneable.copy() method accepts an object of a different type than the implementing class (a list vs. a single object), so you still end up having to write the copy method() which looks virtually identical to the cloneList() method I showed.
                  • 6. Re: Deep Copy of a List
                    jtahlborn
                    Walter Laan wrote:
                    aksarben wrote:
                    In short, you can't do a efficient deep list copy generically. In case anyone is interested, the workaround I came up with is to add a static helper method to the classes whose lists I want to clone. For example, if MyClass implements Cloneable, I added this method to MyClass:
                    It's seems much simpler to let you class implement an interface PublicClonable as DrClap suggested and have a method:
                    public static <T extends PublicCloneable> List<T> copy(final List<T> list) { .. }
                    that wouldn't be a general use method. e.g., one that might accept a list of Strings. you can't add your PublicCloneable interface to the String class. if you use the apache common utils, you can clone any cloneable class.

                    Edited by: jtahlborn on Jan 18, 2011 11:57 AM
                    • 7. Re: Deep Copy of a List
                      866364
                      Hi,

                      Try to make use of GSON to do deep copy.

                      http://sites.google.com/site/gson/gson-user-guide#TOC-Built-in-Serializers-and-Deserializ

                      Look at section.
                      Serializing and Deserializing Collection with Objects
                      You can serialized object list into a json stream using ByteArrayOutputStream and read that back from the same byte array.

                      I think GSON should take cares of deep copy issue. You may also use that to do a Diff for comparing value within the object list.


                      PLEASE NOTE:
                      Collections Limitations
                      * Can serialize collection of arbitrary objects but can not deserialize from it
                      o Because there is no way for the user to indicate the type of the resulting object
                      * While deserializing, Collection must be of a specific generic type