Java中的集合及深拷贝与浅拷贝
Java是一种面向对象的编程语言,其中集合是常用的数据结构之一,具有方便快捷的特点。在Java开发中,我们常常需要对集合进行复制(拷贝)操作。但是,拷贝操作并不是简单的复制,而应该分为浅拷贝和深拷贝两种不同的方式,本文将分别介绍Java中集合的浅拷贝和深拷贝实现方法。
集合简介
Java中的集合是一种用于存储对象的容器,其中包括List、Set、Map等多种类型。集合的特点是可以动态地增加、删除和修改其中的元素。Java中的集合框架分为两个接口:Collection和Map,其中Collection是所有集合接口的根接口,其常用的子接口包括List、Set和Queue。Map接口表示键-值映射,常用的实现类有HashMap和TreeMap。
浅拷贝
浅拷贝是指拷贝对象时,只复制对象的引用而不是对象本身。这意味着拷贝后的对象与原始对象共享同一个内存地址,对于引用类型的成员变量,拷贝后的对象和原始对象都指向同一个实例。
在Java中,可以通过调用Object类的clone()方法实现浅拷贝。该方法会复制对象的字段,但是对于引用类型的字段,仅复制其引用,而不会复制引用指向的对象。
下面是一个示例代码,演示了如何使用clone()方法实现集合的浅拷贝。
import java.util.ArrayList;
import java.util.List;
class Person implements Cloneable {
private String name;
private int age;
private List<String> hobbies;
public Person(String name, int age, List<String> hobbies) {
this.name = name;
this.age = age;
this.hobbies = hobbies;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class ShallowCopyDemo {
public static void main(String[] args) throws CloneNotSupportedException {
List<Person> list1 = new ArrayList<>();
List<String> hobbies = new ArrayList<>();
hobbies.add("reading");
hobbies.add("swimming");
Person person1 = new Person("Tom", 20, hobbies);
list1.add(person1);
List<Person> list2 = (List<Person>) ((ArrayList<Person>) list1).clone();
System.out.println(list1 == list2);
System.out.println(list1.get(0) == list2.get(0));
System.out.println(list1.get(0).getHobbies() == list2.get(0).getHobbies());
}
}
在上面的示例代码中,我们创建了一个Person类,其中包含一个List类型的成员变量hobbies。然后,我们创建了一个List类型的集合list1,并向其中添加一个Person对象person1。接着,我们通过调用list1的clone()方法创建了一个新的集合list2,然后比较list1和list2、person1和list2中的Person对象以及person1和list2中的Person对象的hobbies是否相同。可以看到,由于是浅拷贝,list1和list2、person1和list2中的Person对象及其hobbies都是共享同一块内存空间的。
深拷贝
与浅拷贝不同,深拷贝是指拷贝对象时,不仅复制对象的引用,而且复制引用指向的对象,即创建一个全新的对象,并将原始对象中的所有字段值复制到新对象中。这样做的好处是,新对象和原始对象之间不存在任何关联,对新对象的修改不会影响原始对象。
在Java中,实现深拷贝的方法有多种,下面介绍两种常用的方式。
1. 序列化与反序列化
Java中的序列化可以将对象转换为字节流,而反序列化则可以将字节流还原为对象。利用这一特性,我们可以通过将对象序列化为字节流,然后再反序列化成新对象的方式实现深拷贝。
下面是一个示例代码,演示了如何使用序列化和反序列化实现集合的深拷贝。
import java.io.*;
import java.util.ArrayList;
import java.util.List;
class Person implements Serializable {
private String name;
private int age;
private List<String> hobbies;
public Person(String name, int age, List<String> hobbies) {
this.name = name;
this.age = age;
this.hobbies = hobbies;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
}
public class DeepCopyDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
List<Person> list1 = new ArrayList<>();
List<String> hobbies = new ArrayList<>();
hobbies.add("reading");
hobbies.add("swimming");
Person person1 = new Person("Tom", 20, hobbies);
list1.add(person1);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(list1);
oos.flush();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
List<Person> list2 = (List<Person>) ois.readObject();
System.out.println(list1 == list2);
System.out.println(list1.get(0) == list2.get(0));
System.out.println(list1.get(0).getHobbies() == list2.get(0).getHobbies());
}
}
在上面的示例代码中,我们创建了一个Person类,其中包含一个List类型的成员变量hobbies。然后,我们创建了一个List类型的集合list1,并向其中添加一个Person对象person1。接着,我们通过将list1序列化为字节流,然后再将字节流反序列化为新的List对象list2,实现了深拷贝。最后,我们比较list1和list2、person1和list2中的Person对象以及person1和list2中的Person对象的hobbies是否相同。可以看到,由于是深拷贝,list1和list2、person1和list2中的Person对象及其hobbies均不是共享同一块内存空间的。
2. 手动递归拷贝
手动递归拷贝是另一种实现深拷贝的方式,其思路是先创建一个空的新对象,然后递归地复制原始对象中的所有字段值到新对象中。对于引用类型的字段,需要继续递归拷贝其指向的对象,直到所有字段值均被复制到新对象中。
下面是一个示例代码,演示了如何使用手动递归拷贝实现集合的深拷贝。
import java.util.ArrayList;
import java.util.List;
class Person {
private String name;
private int age;
private List<String> hobbies;
public Person(String name, int age, List<String> hobbies) {
this.name = name;
this.age = age;
this.hobbies = hobbies;
}
public String getName() {
return name;
}
publicvoid setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
public Person deepCopy() {
List<String> newHobbies = new ArrayList<>();
for (String hobby : hobbies) {
newHobbies.add(hobby);
}
return new Person(name, age, newHobbies);
}
}
public class DeepCopyDemo2 {
public static void main(String[] args) {
List<Person> list1 = new ArrayList<>();
List<String> hobbies = new ArrayList<>();
hobbies.add("reading");
hobbies.add("swimming");
Person person1 = new Person("Tom", 20, hobbies);
list1.add(person1);
List<Person> list2 = new ArrayList<>();
for (Person person : list1) {
list2.add(person.deepCopy());
}
System.out.println(list1 == list2);
System.out.println(list1.get(0) == list2.get(0));
System.out.println(list1.get(0).getHobbies() == list2.get(0).getHobbies());
}
}
在上面的示例代码中,我们创建了一个Person类,其中包含一个List类型的成员变量hobbies。然后,我们创建了一个List类型的集合list1,并向其中添加一个Person对象person1。接着,我们通过手动递归拷贝的方式,创建了一个新的集合list2,并将list1中的所有Person对象递归拷贝到list2中。最后,我们比较list1和list2、person1和list2中的Person对象以及person1和list2中的Person对象的hobbies是否相同。可以看到,由于是深拷贝,list1和list2、person1和list2中的Person对象及其hobbies均不是共享同一块内存空间的。文章来源:https://www.toymoban.com/news/detail-732903.html
总结
在Java中,集合是一种常用的数据结构,而集合的拷贝操作又分为浅拷贝和深拷贝两种方式。浅拷贝只复制对象的引用,而深拷贝则复制引用指向的对象,创建一个全新的对象。实现浅拷贝可以通过调用Object类的clone()方法或者手动复制对象的字段实现,而实现深拷贝可以通过序列化与反序列化或者手动递归拷贝实现。在实际开发中,我们应该根据具体情况选择合适的拷贝方式,以保证代码的正确性和性能。文章来源地址https://www.toymoban.com/news/detail-732903.html
到了这里,关于Java中的集合及深拷贝与浅拷贝的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!