標籤

星期六, 7月 23, 2011

Java 5以上有關泛型集合拷貝操作的問題

  • 緣起:
昨天辦公室裡同事在問我有關JDK5以上有關泛型集合拷貝操作的問題,他的需求是希望能保留原始集合內所有物件之內容,因此先將原始的集合先行拷貝一份至記憶體內,然後針對這份拷貝出來的集合在行修改操作,這樣一來既可以保留原來的那一份,又可以毫無顧慮地對拷貝出來的這份恣意地修改。
  • 問題
但是問題是當他使用集合的拷貝方法時,如:ArrayList.clone()時,Java似乎並沒有真的在記憶體內,重新拷貝新的集合到另一快新的記憶體區塊內。導致他怎麼操作修改新的那份集合,都會連帶異動到原始集合內的資料。
  • 解法
簡單地說,以Dog這個類別為例,就是要實作Cloneable這個介面的clone()方法即可。
範例程式碼如下:
  • Dog.java
public class Dog implements Cloneable {

private String kind;
private String color;
public Dog(String kind, String color) {
super();
this.kind = kind;
this.color = color;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
  • ListCloneTest.java
import java.util.ArrayList;

public class ListCloneTest {

/**
* @param args
* @throws CloneNotSupportedException
*/
public static void main(String[] args) throws CloneNotSupportedException {
// TODO Auto-generated method stub
ArrayList oldDogs = new ArrayList();
ArrayList newDogs;
oldDogs.add(new Dog("a", "white"));
oldDogs.add(new Dog("b", "block"));

newDogs = new ArrayList(oldDogs.size());
for(Dog dog : oldDogs){
newDogs.add((Dog) dog.clone());
}
newDogs.get(0).setColor("yellow");
newDogs.get(1).setKind("d");
System.out.println("Old Dogs#1 : kink="+oldDogs.get(0).getKind()+" color="+oldDogs.get(0).getColor());
System.out.println("New Dogs#1 : kink="+newDogs.get(0).getKind()+" color="+newDogs.get(0).getColor());
System.out.println("Old Dogs#2 : kink="+oldDogs.get(1).getKind()+" color="+oldDogs.get(1).getColor());
System.out.println("New Dogs#2 : kink="+newDogs.get(1).getKind()+" color="+newDogs.get(1).getColor());
}

}
  • 輸出結果:
Old Dogs#1 : kink=a color=white
New Dogs#1 : kink=a color=yellow
Old Dogs#2 : kink=b color=block
New Dogs#2 : kink=d color=block