集合深度拷贝

大家常见的拷贝克隆的方法对于集合来说都是浅层拷贝即只是拷贝一个引用。

诸如:Collections.addAll() 、Collections.copy(des,src)、list.clone、new ArrayList(list)等都是浅层拷贝,这种很容易造成数据的不安全。

要安全的拷贝,深度的拷贝,要通过流-对象流。

笔者自己封装的深度拷贝工具类:

package com.wlt.collection;

import java.io.*;
import java.util.List;

/**
 * 集合的普通拷贝克隆复制都是浅层的,下面介绍一种基于对象流的深度拷贝
 * @author 魏霖涛
 * @since 2018/2/28 0028
 */
public class DeepCopy {
    public static <T> List<T> deepCopyList(List<T> source) throws IOException, ClassNotFoundException {
        List<T> target;
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(source);

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        target = (List<T>) objectInputStream.readObject();
        return  target;
    }
}

测试:

public static void main(String[] args) throws IOException, ClassNotFoundException {
        WltDeepcopy wltClone = new WltDeepcopy("wlt");

        System.out.println("deepCopy-集合使用-------------深度拷贝");
        //Arrays.asList("1","2")返回的是只读的集合,而new ArrayList<>(Arrays.asList("1","2"))返回的是正常的集合
        ArrayList list = new ArrayList(Arrays.asList(wltClone,"2"));
        ArrayList clonelist = (ArrayList) deepCopyList(list);
        System.out.println("modify---之前");
        System.out.println(list);
        System.out.println(clonelist);
        System.out.println(list.hashCode());
        System.out.println(clonelist.hashCode());
        //下面这种是把集合元素的引用所指的对象属性改变,所以会引发连锁改变
        ((WltDeepcopy)list.get(0)).setName("modify");
        //下面这种是直接把集合的引用给改变了,所以不会引发连锁改变
//        list.set(0,new WltClone("happy"));
        System.out.println("modify---之后");
        System.out.println(list);
        System.out.println(clonelist);
    }

测试对象类:

class WltDeepcopy implements Serializable{
    private String name;

    public WltDeepcopy(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    @Override
    public String toString() {
        return "WltClone{" +
                "name='" + name + '\'' +
                '}';
    }
}

测试结果:

可以发现,拷贝之后的对象的hashcode(更正下,这边的hashcode是集合的hashcode,所以肯定是不一样的,拷贝后的对象,应该要把对象取出来打印对象的hashcode--2018/3/2)是不一样的,说明拷贝前后的对象不是同一个,修改其中一个属性,发现不会引发连锁改变。

2018/3/4更新 添加try-with-source自动关闭流

    public static <T> List<T> deepCopyList(List<T> source) throws IOException, ClassNotFoundException {
        List<T> target;
        try(
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
                ){
            objectOutputStream.writeObject(source);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            target = (List<T>) objectInputStream.readObject();
            return  target;
        }
    }

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
在 Java 中,可以使用以下两种方式实现集合的深拷贝: 1. 使用序列化与反序列化 这种方式需要将集合对象先序列化成字节数组,再通过反序列化生成一个新的对象。由于序列化会将对象的所有属性都进行深拷贝,因此可以实现集合的深拷贝。示例代码如下: ```java public static <T extends Serializable> 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; } ``` 2. 遍历拷贝 这种方式需要手动遍历集合中的每个元素,对每个元素进行深拷贝,最后将所有拷贝后的元素添加到一个新的集合中。示例代码如下: ```java public static <T extends Serializable> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException { List<T> dest = new ArrayList<T>(src.size()); for (T element : src) { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(element); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream in = new ObjectInputStream(byteIn); @SuppressWarnings("unchecked") T copy = (T) in.readObject(); dest.add(copy); } return dest; } ``` 需要注意的是,这两种方式都要求集合中的元素必须实现 Serializable 接口。如果集合中的元素没有实现 Serializable 接口,则需要手动实现深拷贝方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独行侠_阿涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值