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-01-12 22:13:23

    UINavigationController和UIScrollView滚动-92

    如果navigation bar或者toolbar不透明,view controller就无法让它的view全屏显示。换句话说,如果不希望view controller里面的view全屏显示,就应该把navigation bar设为不透明。

  • 2021-01-12 22:15:46

    NSLog各种打印占位符

    打印CGRect : NSLog(@"%@",NSStringFromCGRect(someCGRect)); 或者CFShow(NSStringFromCGRect(someCGRect));

  • 2021-01-13 13:36:29

    shortid nodejs短id生成器

    短ID在实际运用中很广泛, 其中比较典型的运用就是短地址。 市面上肯定有不少开源的生成短ID库, 基于node.js的估计也不少。 鉴于本人已然是node.js的脑残粉(本职java开发), 很多业余项目从前端到后端都基于javascript开发, 加上npm和bower的包管理以及grunt的打包工具, 在项目开发过程中体验特别酸爽。 由于当时项目前后端都会用到短ID, 但没找到合适的库同时支持npm和bower的(可能孤陋寡闻). 因此自己乐此不疲地又造了个轮子js-shortid(夷,为什么会说又呢?!). 下面主要介绍它的实现方案, 自认为比较优雅简洁。

  • 2021-01-13 17:23:21

    CREATE TABLE 表名 AS SELECT 语句 快速复制表但是锁表

    注意Table2的主键约束,如果Table2有主键而且不为空,则 field1, field2…中必须包括主键 在执行语句的时候,MySQL是逐行加锁的(扫描一个锁一个),直至锁住所有符合条件的数据,执行完毕才释放锁。所以当业务在进行的时候,切忌使用这种方法。 在RR隔离级别下,还会加行锁和间隙锁

  • 2021-01-13 17:27:04

    Navicat配置mysql数据库用户权限

    用数据库的时候就会遇到有多个用户,分配用户权限的情况,有些用户只读,有些用户可以读写,有些用户只能操作一个或者多个数据库,如何给mysql的用户设置权限,我这里描述一下如何用navicat图形操作分配用户权限