Magnus
Magnus

Reputation: 728

Is there a method in the standard API which can deep clone a list?

In about 30 days, I'm going to participate in a Java contest. At the contest, we'll be handed a computer with Eclipse and the Java 1.7 API. I'm practicing on the tasks from the previous year's contest, and I repeatedly find the need to deep clone a list. With limited time and the only the Java 1.7 API available, is there any way to do this?

I've seen several solutions to this already, including

But these solutions are either not available to me at the contest or too time consuming. Right now, I need to deep clone an ArrayList of objects that also contain ArrayLists.

Does anyone know if this is even possible? Thanks for all help!

Upvotes: 1

Views: 135

Answers (2)

Roland
Roland

Reputation: 18415

Instead of invoking clone you could also write everything to a ByteArrayOutputStream and read it in again.

See if this helps you:

  static public <T> T deepCopy(T oldObj) throws Exception {
    ObjectOutputStream oos = null;
    ObjectInputStream ois = null;
    try {
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      oos = new ObjectOutputStream( bos);
      oos.writeObject( oldObj);
      oos.flush();
      ByteArrayInputStream bin = new ByteArrayInputStream( bos.toByteArray());
      ois = new ObjectInputStream( bin);

      return (T) ois.readObject();
    } catch( Exception e) {
      e.printStackTrace();
      throw ( e);
    } finally {
      if( oos != null) {
        oos.close();
      }
      if( ois != null) {
        ois.close();
      }
    }
  }

Usage e. g.:

public class Testing {

  public static void main(String[] args) throws Exception {

    List<Object> list = new ArrayList<>();
    list.add( "A");
    list.add( "B");
    list.add( 1);
    list.add( 2);
    list.add( new BigDecimal( 123.456839572935879238579238754938741321321321321593857));
    list.add( new MyParentObject( 12345, "abcdef", new MyChildObject( "child")));

    List clone = (List) Tools.deepCopy( list);

    for( Object obj: clone) {
      System.out.println( obj);
    }

    System.exit(0);
  }

  private static class MyParentObject implements Serializable {
    int a;
    String b;
    MyChildObject child;

    public MyParentObject(int a, String b, MyChildObject child) {
      super();
      this.a = a;
      this.b = b;
      this.child = child;
    }

    public String toString() {
      return a + ", " + b + ", " + child;
    }
  }

  private static class MyChildObject implements Serializable {
    String s;

    public MyChildObject( String s) {
      this.s = s;
    }

    public String toString() {
      return s;
    }
  }
}

Output:

A
B
1
2
123.456839572935876958581502549350261688232421875
12345, abcdef, child

Upvotes: 0

Kevin Workman
Kevin Workman

Reputation: 42176

This is going to depend entirely on what's in the List. So, the short answer is: no.

You could try serializing the whole List, but that requires everything in the List also be serializable. You could write a deepClone() method that calls the clone() method on everything in the List, but that depends on every Object in the List correctly implementing the clone() method.

The whole reason this is a contest question is there isn't a quick one-size-fits-all solution.

Upvotes: 2

Related Questions