项目开发中,将多个对象(实体类)放到集合中,遇到一个List A 集合中,把List A 集合数据复制到另外的一个List B集合中,当修改新的List B集合的数据,旧的List A 集合也跟着修改了。
问题描述
- 在内存中创建 List A 和 List B 在内存中会开辟空间
- List A集合中添加的对象,在内存也开辟空间
- 将List A集合的数据添加到 List B集合中,两个集合是不相等的,但是集合中的对象都指向的同一个,所以修改List B集合中的对象,List A 的集合也就改变了
- 方案:使List B 中对象 和 List A 中的对象不一样。可以达到改变 List B 集合中的对象,而不影响 List A 集合的数据
解决方案
- 先创建实体类对象
定义实体类
public class TestList {
static class P implements Cloneable {
public P(int id, String name) {
this.id = id;
this.name = name;
}
int id;
String name;
@Override
public String toString() {
return "P{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
@Override
protected P clone() throws CloneNotSupportedException {
return (P) super.clone();
}
}
static class PP implements Serializable {
public PP(int id, String name) {
this.id = id;
this.name = name;
}
int id;
String name;
@Override
public String toString() {
return "P{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
- 使用深拷贝,让实体类实现 Cloneable , 同时复写 object 的 clone() 方法
public class TestList {
public static void main(String[] args) {
modelCopy();
}
private static void modelCopy() {
ArrayList<P> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(new P(i, "i " + i));
}
ArrayList<P> listNew = new ArrayList<>();
for (P p : list) {
try {
listNew.add(p.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < listNew.size(); i++) {
if (listNew.get(i).id == 1) {
P p1 = listNew.get(i);
p1.name = "zhang";
break;
}
}
System.out.println(" 旧 "+list);
System.out.println(" 新 "+listNew);
}
}
- 不使用深拷贝:使用ArrayList 中的 clone() 复制一个新的 ArrayList 集合, 但是需要对修改对象进行重新设值,再赋值到当期位置的对象。
public class TestList {
public static void main(String[] args) {
collDeepNew();
}
private static void collDeepNew() {
System.out.println("循环赋值 创建新的对象 -------");
ArrayList<PP> listP = new ArrayList<>();
for (int i = 0; i < 10; i++) {
listP.add(new PP(i, "i " + i));
}
ArrayList<PP> newListP = (ArrayList<PP>) listP.clone();
if (newListP != null) {
for (int i = 0; i < newListP.size(); i++) {
if (i == 1) {
PP pp = new PP(newListP.get(i).id, newListP.get(i).name);
pp.name = "zhang";
newListP.set(i, pp);
break;
}
}
System.out.println("循环赋值 原list值:" + listP);
System.out.println("循环赋值 新list值:" + newListP);
}
System.out.println("---------------------");
}
}
- 不使用深拷贝:使用读流文件
public class TestList {
public static void main(String[] args) {
collDeepNew();
}
private static void collDeep() {
System.out.println("DeepCopyUtil -------- 深拷贝 需要实体类继承 Serializable");
List<PP> listP = new ArrayList<>();
for (int i = 0; i < 10; i++) {
listP.add(new PP(i, "i " + i));
}
//list深度拷贝
List<PP> newListP = DeepCopyUtil.deepCopy(listP);
if (newListP != null) {
for (int i = 0; i < newListP.size(); i++) {
if (i == 1) {
newListP.get(i).name = "zhang";
break;
}
}
System.out.println("原list值:" + listP);
System.out.println("新list值:" + newListP);
}
}
}
public class DeepCopyUtil {
/**
* List深拷贝 条件:需要model实现Serializable
*/
public static <T> List<T> deepCopy(List<T> t) {
try {
// 写入字节流
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(t);
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
return (List<T>) in.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
总结