Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: clone arbitrary Collection through reference to Collection

Suppose you've a reference of type java.util.Collection in a method and cannot say what implementation of java.util.Collection will it point to at run time, is it possible to clone the Collection?

I wanted to implement a generic method which will filter any type of collection given. Hence the method will take java.util.Collection as input. However beyond this, I didn't want to modify the original collection, so I wanted to clone the collection.

like image 912
Rnet Avatar asked Feb 02 '11 14:02

Rnet


2 Answers

Unfortunaly the interface Collection does not say anything about implementing Clonable Interface.


But what you can always do is copy the collection:

List<T> copy = new ArrayList<T>(original);

If you only want to make sure that it is not modified then wrap it with an unmodidfiable collection instead of cloning it:

Collection<T> unmodifiable = Collections.unmodifiableCollection(original);
like image 78
Ralph Avatar answered Nov 15 '22 18:11

Ralph


I'm going to demonstrate in Scala, becuase it has a REPL where I can test, but the same semantics should work in Java.

import java.util._
val orig = new LinkedList[Int]
val theClone = orig.clone

The Scala REPL tells me that theClone has static type Object (you can cast this to Collection[Int] or LinkedList[Int]), but the dynamic type of the clone is still LinkedList.

Now I suppose what you want is a method that returns a static type LinkedList when it recieves a static type LinkedList and returns a static type ArrayList when it recieves a static type ArrayList, etc. in which case

def doClone[C <: Collection[_]](orig:C) = {
  val cloneMethod = orig.getClass.getDeclaredMethod("clone")
  if (cloneMethod.isAccessible)
    cloneMethod.invoke(orig).asInstanceOf[C]
  else
    throw new CloneNotSupportedException
}

In Java, I think that's

<C extends Collection<?> > C doClone (C orig) {
   java.lang.reflect.Method cloneMethod = 
     orig.getClass().getDeclaredMethod("clone");
   if (cloneMethod.isAccessible())
     return (C) cloneMethod.invoke(orig);
   else
     throw new CloneNotSupportedException();
}
like image 44
Ken Bloom Avatar answered Nov 15 '22 20:11

Ken Bloom