使用Map.clear()、List.clear()方法,清空时注意!

对 Map、List 对象进行清空操作时,常常会使用 clear() 方法。

例如,清空 Map

java 复制代码
	Map map = new HashMap();
	map.put("key1","value1");
	map.put("key2","value2");
	System.out.println(map.size()); //2
	map.clear();
	System.out.println(map.size()); //0

换做 List 也是同样的用法

java 复制代码
	List list = new ArrayList<>();
	list.add("1");
	list.add("2");
	System.out.println(list.size()); //2
	list.clear();
	System.out.println(list.size()); //0

但是!!!

本文想要说的是,需要注意,如果使用clear()方法, Map被清空的同时,原本对Map的引用会一起被清空!!!

代码举例:

java 复制代码
	List list = new ArrayList<>();
	Map map = new HashMap();
	List listTemp = new ArrayList<>();
	for(int i=0; i<3; i++){
	    map.clear();
	    for(int j=0; j<3; j++){
	        listTemp.add("i="+i+";j="+j);
	    }
	    map.put(""+i,listTemp);
	    list.add(map);
	}
	System.out.println(list);

这段代码也很简单,两层循环。

最里层向 listTemp 中添加数据,循环三次;

外层向 map 中添加 listTemp,key 值为循环次数的值;

每一次外层的循环都会清空之前循环的 map;

每一次外层的循环将 map 添加到外层 list 中。

根据这段代码,我们期待的结果是:

[{

0 = i = 0;j = 0, i = 0;j = 1, i = 0;j = 2, i = 1;j = 0, i = 1;j = 1, i = 1;j = 2, i = 2;j = 0, i = 2;j = 1, i = 2;j = 2

}, {

1 = i = 0;j = 0, i = 0;j = 1, i = 0;j = 2, i = 1;j = 0, i = 1;j = 1, i = 1;j = 2, i = 2;j = 0, i = 2;j = 1, i = 2;j = 2

}, {

2 = i = 0;j = 0, i = 0;j = 1, i = 0;j = 2, i = 1;j = 0, i = 1;j = 1, i = 1;j = 2, i = 2;j = 0, i = 2;j = 1, i = 2;j = 2

}]

而实际上,我们能够得到的结果是:

[{

2 = i = 0;j = 0, i = 0;j = 1, i = 0;j = 2, i = 1;j = 0, i = 1;j = 1, i = 1;j = 2, i = 2;j = 0, i = 2;j = 1, i = 2;j = 2

}, {

2 = i = 0;j = 0, i = 0;j = 1, i = 0;j = 2, i = 1;j = 0, i = 1;j = 1, i = 1;j = 2, i = 2;j = 0, i = 2;j = 1, i = 2;j = 2

}, {

2 = i = 0;j = 0, i = 0;j = 1, i = 0;j = 2, i = 1;j = 0, i = 1;j = 1, i = 1;j = 2, i = 2;j = 0, i = 2;j = 1, i = 2;j = 2

}]

可以看到,三条数据完全相同。

而这意味着,我们在使用clear()清空了Map之后,再次对Map进行赋值的时候,添加了原Map的List,其中元素随之发生变化。

另写部分代码验证:

java 复制代码
	Map map = new HashMap();
	map.put("1","11");
	map.put("2","22");
	List<Map> list = new ArrayList<>();
	list.add(map);
	System.out.println(list);
	map.clear();
	map.put("3","33");
	System.out.println(list);
	map.put("2","22");
    System.out.println(list);

控制台输出为

{1=11, 2=22}

{3=33}

{2=22, 3=33}

由此,验证了我们的想法。

Map 是这样,List 也不例外。

将上述例子稍作改动,如下:

java 复制代码
	List<Map> list = new ArrayList<>();
    List listTemp = new ArrayList<>();
    for(int i=0; i<3; i++){
        listTemp.clear();
        for(int j=0; j<3; j++){
            listTemp.add("i="+i+";j="+j);
        }
        Map map = new HashMap();
        map.put(""+i,listTemp);
        list.add(map);
    }
    System.out.println(list);

这一次的执行结果如下:

[{

0 = i = 2;j = 0, i = 2;j = 1, i = 2;j = 2

}, {

1 = i = 2;j = 0, i = 2;j = 1, i = 2;j = 2

}, {

2 = i = 2;j = 0, i = 2;j = 1, i = 2;j = 2

}]

可以看到在外层 list中,每个map元素内部的 listTemp 都是相同的,说明同样被更新了。

总结

我们也总结得出:Map、List 若被引用,那么后续的清空、修改、增加等操作,仍会影响到原本的引用

使用的时候要注意这一点!

相关推荐
withoutfear1 天前
IntelliJ IDEA卡顿内存分配不足和索引被频繁触发问题解决办法
java·ide·intellij-idea
大圣编蚕1 天前
Java StringWriter 详解:从入门到实战
java·开发语言·python
码行山野赴时序归途1 天前
C语言预处理指令:编译前的“幕后导演“
c语言·开发语言
golang学习记1 天前
Go 1.27新特性: json/v2使用有趣指南
开发语言·golang·json
老苗项目实战1 天前
Java工程师高频面试题(基于近一年的真实面试记录整理)
java·开发语言·面试·预见猿份·老苗项目实战
小小、码农1 天前
C++11右值引用与移动语义 —— 从拷贝资源到转移资源
开发语言·网络·c++·网络协议
陈皮波比茶1 天前
分布式任务调度xxl-job
java·分布式
for_ever_love__1 天前
python基础语法学习: requirements.txt
开发语言·python·学习
XiaoYu1__1 天前
JavaGUI文件管理系统开发实战:从静态展示到动态交互的演进
java·开发语言
for_ever_love__1 天前
python基础语法学习: 动态类型
开发语言·python·学习