List复制的方法有哪些?

460 阅读2分钟

定义一段基础代码便于测试

List<Person> srcList=new ArrayList<Person>();  
Person p1=new Person(20,"123");  
Person p2=new Person(21,"ABC");  
Person p3=new Person(22,"abc");  
srcList.add(p1);  
srcList.add(p2);  
srcList.add(p3); 

浅复制

1.遍历循环复制

List<Person> destList=new ArrayList<Person>();  
for(Person p : srcList){  
    destList.add(p);  
}
system.out.println(destList.toString())  

2.使用构造方法复制 (通过ArrayList的构造方法来复制集合内容,同样是浅复制,在修改了源数据集合后,目标数据集合对应内容也发生了改变)

List<Person> destList=new ArrayList<Person>(srcList);  
system.out.println(destList.toString())

3.使用list.addAll()方法复制

List<Person> destList=new ArrayList<Person>();  
destList.addAll(srcList);  

4.System.arraycopy()方法复制

Person[] srcPersons=srcList.toArray(new Person[0]);  
Person[] destPersons=new Person[srcPersons.length];  
System.arraycopy(srcPersons, 0, destPersons, 0, srcPersons.length); 

深度复制

5.使用序列化方法复制(相对靠谱)

public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {  
    ByteArrayOutputStream byteOut = new ByteArrayOutputStream();  
    ObjectOutputStream out = new ObjectOutputStream(byteOut);  
    out.writeObject(src);  

    ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  
    ObjectInputStream in = new ObjectInputStream(byteIn);  
    @SuppressWarnings("unchecked")  
    List<T> dest = (List<T>) in.readObject();  
    return dest;  
}  

List<Person> destList=deepCopy(srcList);  

其实,上面这些不靠谱List深复制的做法在某些情况是可行的,这也是为什么有些人说这其中的一些做法是可以实现深复制的原因。哪些情况下是可行(本质上可能还是不靠谱)的呢?比如List<String>这样的情况。我上面使用的是List<Person>,它和List<String>的区别就在于Person类和String类的区别,Person类提供了破坏数据的2个setter方法。因此,在浅复制的情况下,源数据被修改破坏之后,使用相同引用指向该数据的目标集合中的对应元素也就发生了相同的变化。
因此,在需求要求必须深复制的情况下,要是使用上面提到的方法,请确保List<T>中的T类对象是不易被外部修改和破坏的。

另一个问题

上面实体类是实现了Serializable接口,那么使用上面方法可以实现深度复制,但是如果是实现了Android中的Parcelable接口,上面方法就不行了!
那么一个比较统一的且可以实现深度复制的方法就是:将我们的List<T>转换为json,再把json转回List<T>
这里我们使用Gson来转换:

public static <T> List<T> jsonToList(String json, Class<T> clazz) {
    Type type = new TypeToken<ArrayList<JsonObject>>() {
    }.getType();
    ArrayList<JsonObject> jsonObjects = new Gson().fromJson(json, type);
    ArrayList<T> arrayList = new ArrayList<T>();
    for (JsonObject jsonObject : jsonObjects) {
        arrayList.add(gson.fromJson(jsonObject, clazz));
    }
    return arrayList;}

使用的时候:

Gson gson = new Gson();
String jsonTran = gson.toJson(sourceList);
List<T> deepCloneList= jsonToList(jsonTran, T.class);

这样deepCloneList就是源list深度复制的list了!且修改源list,并不影响复制之后的list!