This discussion is archived
7 Replies Latest reply: Jun 2, 2011 10:33 PM by 866364 RSS

Deep Copy of a List

aksarben Journeyer
Currently Being Moderated
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 Expert
    Currently Being Moderated
    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 Journeyer
    Currently Being Moderated
    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 Expert
    Currently Being Moderated
    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 Expert
    Currently Being Moderated
    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 Journeyer
    Currently Being Moderated
    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 Expert
    Currently Being Moderated
    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 Newbie
    Currently Being Moderated
    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

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points