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是指在需要深拷贝的情况下采取的措施