向List中添加map被覆盖

1.这里放入list里的是不同的map,虽然map d是同一个map,但是指向了不同的地址

当我们把alist.get(i)赋值给dmap的时候,就已经把dmap的地址指向了对应的aList中的某个map,例如d=a,这时a和d是完全相等的两个对象,他们在栈上的引用地址是相同的,当a赋值给d的时候,d的引用已经指向了a的内存区域,这时候我们修改d的话,实际上修改的也是a,当循环到d=b的时候,d在栈上的引用地址又指向了b,以此类推

    public static void main(String argv[]) {
        List<Map> aList = new ArrayList<>();
        Map a = new HashMap<>();
        Map b = new HashMap<>();
        Map c = new HashMap<>();
        a.put("a", 1);
        b.put("a", 2);
        c.put("a", 3);
        aList.add(a);
        aList.add(b);
        aList.add(c);

        System.out.println(aList);

        List<Map> bList = new ArrayList<>();
        Map d = new HashMap<>();
        for (int i = 0; i <= 2; i++) {
            d = aList.get(i);
            d.put("b", i);
            bList.add(d);
        }
        System.out.println(bList);

    }
[{a=1}, {a=2}, {a=3}]
[{a=1, b=0}, {a=2, b=1}, {a=3, b=2}]

2.由于第一个for循环中的amap在栈上并没有改变过引用,所以amap所指向的对象是一直是同一个,所以导致list数据全被覆盖

    public static void main(String argv[]) {
        
        Map<String,Object> amap = new HashMap<>();
        List<Map<String,Object>> alist = new ArrayList<>();
        for(int i=0;i<3;i++){
    //      amap=new HashMap<>();
            amap.put("a", i);
            amap.put("b", i);
            alist.add(amap);
        }
        System.out.println(alist);
[{a=2, b=2}, {a=2, b=2}, {a=2, b=2}]

3.接上一个例子,这里第二个for循环明明每次都是新建了一次bmap,然后数据还是被覆盖掉,主要问题还是出现在第一个for循环中,因为整段程序中自始至终只有一个可用对象amap

这种复制可以称为浅复制,只是复制了对象的引用而已,虽然第二个for循环的bmap是循环建立的,并且每次new一个对象的时候,都会在内存区域开辟一个新的内存空间准备使用,当amap赋值给bmap的时候,bmap在栈中的引用已经指向了amap在堆中的位置,新开出的bmap内存空间是没有引用的,对于没有任何引用的内存区域或栈中引用指向了null,gc会进行回收,所以这样写不仅没用,还增加了底层的负担

 public static void main(String argv[]) {

        Map<String,Object> amap = new HashMap<>();
        List<Map<String,Object>> alist = new ArrayList<>();
        for(int i=0;i<3;i++){
          //amap=new HashMap<>();
            amap.put("a", i);
            amap.put("b", i);
            alist.add(amap);
        }
        System.out.println(alist);

        for(int i = 0;i<alist.size();i++){
            Map bmap = new HashMap<>();
            bmap = alist.get(i);
            bmap.put("hehe",i);
        }
        System.out.println(alist);

    }
[{a=2, b=2}, {a=2, b=2}, {a=2, b=2}]
[{a=2, b=2, hehe=2}, {a=2, b=2, hehe=2}, {a=2, b=2, hehe=2}]

4.综上,第一个for循环中要每次都建立一个新map,而不能只是改变引用,而第二个for循环我们只是引用对象,并不需要创建新对象

    public static void main(String argv[]) {
        List<Map<String,Object>> alist = new ArrayList();
        for(int i=0;i<3;i++){
            Map<String,Object> amap=new HashMap();
            amap.put("a", i);
            amap.put("b", i);
            alist.add(amap);
        }
        System.out.println(alist);

        Map bmap = null;
        for(int i = 0;i<alist.size();i++){
            bmap = alist.get(i);
            bmap.put("hehe",i);
        }
        System.out.println(alist);
    }
[{a=0, b=0}, {a=1, b=1}, {a=2, b=2}]
[{a=0, b=0, hehe=0}, {a=1, b=1, hehe=1}, {a=2, b=2, hehe=2}]

接下来做个测试,看看是否如上所述:

    public static void main(String argv[]) {
        List<Map<String,Object>> alist = new ArrayList();
        for(int i=0;i<3;i++){
            Map<String,Object> amap=new HashMap();
            amap.put("a", i);
            alist.add(amap);
        }
        System.out.println(alist);

        List<Map<String,Object>> blist = new ArrayList();
        Map bmap = null;
        for(int i = 0;i<alist.size();i++){
            bmap = alist.get(i);
            bmap.put("hehe",i);
            blist.add(bmap);
        }

        List<Map<String,Object>> clist = new ArrayList();
        for(int i = 0;i<alist.size();i++){
            Map cmap = new HashMap();
            cmap = blist.get(i);
            cmap.put("haha",i);
            clist.add(cmap);
        }

        System.out.println(alist);
        System.out.println(blist);
        System.out.println(clist);

        System.out.println(alist.get(0)==blist.get(0));
        System.out.println(blist.get(0)==clist.get(0));
    }

输出:

[{a=0}, {a=1}, {a=2}]
[{a=0, haha=0, hehe=0}, {a=1, haha=1, hehe=1}, {a=2, haha=2, hehe=2}]
[{a=0, haha=0, hehe=0}, {a=1, haha=1, hehe=1}, {a=2, haha=2, hehe=2}]
[{a=0, haha=0, hehe=0}, {a=1, haha=1, hehe=1}, {a=2, haha=2, hehe=2}]
true
true

5.如上所述,上述传递的map都是同一个对象,导致获得blist后alist也发生了变化, 那么,如果我们既想保留alist不变,又想在alist的基础上增加新的数据获得blist,那该怎么办呢

这次的需求其实就是指的 深拷贝,真正意义上的复制,真正新开辟了内存,真正在堆中复制了对象

    public static void main(String argv[]) {
        List<Map<String,Object>> alist = new ArrayList();
        for(int i=0;i<3;i++){
            Map<String,Object> amap=new HashMap();
            amap.put("a", i);
            alist.add(amap);
        }
        System.out.println(alist);

        List<Map<String,Object>> blist = new ArrayList();
        for(int i = 0;i<alist.size();i++){
            Map bmap = new HashMap(); 
            bmap.putAll(alist.get(i));
            bmap.put("hehe","a"+i);
            blist.add(bmap);
        }
        
        System.out.println(alist);
        System.out.println(blist);

        System.out.println(alist.get(0)==blist.get(0));
    }

输出

[{a=0}, {a=1}, {a=2}]
[{a=0}, {a=1}, {a=2}]
[{a=0, hehe=a0}, {a=1, hehe=a1}, {a=2, hehe=a2}]
false

总结:1,2,3,4所举例子都是为了说明浅复制的情况,而5是指在需要深拷贝的情况下采取的措施

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

纯洁的小魔鬼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值