文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java中的集合及深拷贝与浅拷贝

2023-09-16 18:28

关注

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均不是共享同一块内存空间的。

总结

在Java中,集合是一种常用的数据结构,而集合的拷贝操作又分为浅拷贝和深拷贝两种方式。浅拷贝只复制对象的引用,而深拷贝则复制引用指向的对象,创建一个全新的对象。实现浅拷贝可以通过调用Object类的clone()方法或者手动复制对象的字段实现,而实现深拷贝可以通过序列化与反序列化或者手动递归拷贝实现。在实际开发中,我们应该根据具体情况选择合适的拷贝方式,以保证代码的正确性和性能。

来源地址:https://blog.csdn.net/stormjun/article/details/131728657

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯