map对象拷贝问题

2018-08-23 15:32:18

map对象赋值:

HashMap<String,Object> hm = new HashMap();

HashMap<String,Object> hmCopy = new HashMap();

hm.put("123", 123);

System.out.println(hm.get("123"));

hmCopy = hm;

hmCopy.remove("123");

System.out.println(hm.get("123"));

输出结果:123    null



这种直接赋值属于对象的引用变化,两个变量指向的是同一个对象


//map拷贝putAll方法:

HashMap<String,Object> hm = new HashMap();

HashMap<String,Object> hmCopy = new HashMap();

hm.put("123", 123);

System.out.println(hm.get("123"));

hmCopy.putAll(hm);

hmCopy.remove("123");

System.out.println(hm.get("123"));

输出结果:123   123



map对象深拷贝:


List<Integer> list = new ArrayList<Integer>();

list.add(100);

list.add(200);


HashMap<String,Object> map = new HashMap<String,Object>();

map.put("basic", 100);//放基本类型数据

map.put("list", list);//放对象


HashMap<String,Object> mapNew = new HashMap<String,Object>();

mapNew.putAll(map);


System.out.println("----数据展示-----");

System.out.println(map);

System.out.println(mapNew);

System.out.println("----更改基本类型数据-----");

map.put("basic", 200);

System.out.println(map);

System.out.println(mapNew);

System.out.println("----更改引用类型数据-----");

list.add(300);

System.out.println(map);

System.out.println(mapNew);

System.out.println("----使用序列化进行深拷贝-----");

mapNew = CloneUtils.clone(map);

list.add(400);

System.out.println(map);

System.out.println(mapNew);

输出结果:

----数据展示-----

{basic=100, list=[100, 200]}

{basic=100, list=[100, 200]}

----更改基本类型数据-----

{basic=200, list=[100, 200]}

{basic=100, list=[100, 200]}

----更改引用类型数据-----

{basic=200, list=[100, 200, 300]}

{basic=100, list=[100, 200, 300]}

----使用序列化进行深拷贝-----

{basic=200, list=[100, 200, 300, 400]}

{list=[100, 200, 300], basic=200}




最上面的两条是原始数据,使用了putAll方法拷贝了一个新的mapNew对象,

中间两条,是修改map对象的基本数据类型的时候,并没有影响到mapNew对象。

但是看倒数第二组,更改引用数据类型的时候,发现mapNew的值也变化了,所以putAll并没有对map产生深拷贝。

最后面是使用序列化的方式,发现,更改引用类型的数据的时候,mapNew对象并没有发生变化,所以产生了深拷贝。

上述的工具类,可以实现对象的深拷贝,不仅限于HashMap,前提是实现了Serlizeable接口。



//附克隆方法:

public static <T extends Serializable> T clone(T obj) {

    T cloneObj = null;

    try {

        // 写入字节流

        ByteArrayOutputStream out = new ByteArrayOutputStream();

        ObjectOutputStream obs = new ObjectOutputStream(out);

        obs.writeObject(obj);

        obs.close();


        // 分配内存,写入原始对象,生成新对象

        ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());

        ObjectInputStream ois = new ObjectInputStream(ios);

        // 返回生成的新对象

        cloneObj = (T) ois.readObject();

        ois.close();

    } catch (Exception e) {

        e.printStackTrace();

    }

    return cloneObj;

}





  • 2021-04-06 17:13:08

    nuxt.js keep-alive和嵌套路由不变化

    因为你错误的使用了 <nuxt>标签。 你应该使用 <nuxt-child keep-alive > </nuxt-child> 因为上层已经使用过了 <nuxt></nuxt>标签。

  • 2021-04-13 09:48:45

    消息中间件之MQ详解及四大MQ比较

    消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开发RocketMQ等。

  • 2021-04-13 09:52:18

    Kafka学习之路 Kafka的简介

    Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可以用于web/nginx日志、访问日志,消息服务等等,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。

  • 2021-04-13 09:53:12

    nodejs操作消息队列RabbitMQ

    消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已。 其主要用途:不同进程Process/线程Thread之间通信。

  • 2021-04-15 10:07:49

    Chrome屏蔽Your connection is not private

    使用Fiddler时如何屏蔽Chrome的证书警告:"Your connection is not private"/"您的连接不是私密连接"(如图1所示)? 启动chrome的时候加上--ignore-certificate-errors命令行参数(如图2所示)即可。

  • 2021-04-15 10:10:00

    Puppeteer 系列踩坑日志—3—开启支持插件

    在使用puppeteer自动化的过程中,会发现其实开启的chrome往往自动禁用了插件功能,如果我们想在自动化测试的过程中,再去使用一些常用的插件提升效率(偷懒)的话,就行不通了,其实解决办法还是有的,我们今天就来讲解这个问题。