Map集合的循环与删除

有一个朋友经常说:最基础的东西最磨人。
这两天遇到一个,哭笑不得的HashMap删除空指针,抓紧时间记录。

一、原始需求

原始需求只是从resourcekeyMap一个普通的HashMap中获取数据存入一个普通的名叫resourceList的ArrayList中
代码如下:

        Collection collection = resourceKeyMap.values();
        collection.forEach((resource)->resourceList.add(resource));

二、增加需求

现在需要将resource中structNodeId为空的数据剔除,就出现空指针异常。

如果没有debug,也没有这个经验的人,一眼看过去发现不了这个空指针,不信你试试。

展示我的原始代码:

       
        Collection collections = resourceKeyMap.values();
        for (Object resource1:collections) {
           Resource resource = (Resource)resource1;
            if(resource.getStructNodeId()!=null){
                resourceList.add(resource);
            }else{
                resourceKeyMap.remove(resource.getResourceId());
            }
        }

很清晰的代码,是吧。

三、发现异常,解释异常

这行代码

resourceKeyMap.remove(resource.getResourceId());

在删除的时候,会出现异常
分析原因:

在遍历HashMap的元素过程中,Map中有key对应的指针进行下一个数据的指向,如果此时删除了当前所在元素,下一个待访问的元素的指针也由此丢失了,

正常情况下,此时应该放上源码,再做解释,但是太啰嗦了,今天时间紧促,着急吃饭,直接上解释:

HahMap基本原理:

先声明一个下标范围比较大的数组来存储元素。另外设计一个哈希函数(也叫做散列函数)来获得每一个元素的Key(关键字)的函数值(即数组下标,hash值)相对应,数组存储的元素是一个Entry类,这个类有三个数据域,key、value(键值对),next(指向下一个Entry)。

请注意这个next

例如, 第一个键值对A进来。通过计算其key的hash得到的index=0。记做:Entry[0] = A。
第二个键值对B,通过计算其index也等于0, HashMap会将B.next =A,Entry[0] =B, 第三个键值对
C,index也等于0,那么C.next = B,Entry[0] =
C;这样我们发现index=0的地方事实上存取了A,B,C三个键值对,它们通过next这个属性链接在一起。我们可以将这个地方称为桶。

如果删除了这个节点,那就直接删除了这个Entry,包括key、value,next,所以再进行遍历的时候,发现存在值,但是死活找不到,无奈之下,只能报异常,引起注意。

四、解决办法

        //iterator遍历
        for(Iterator<Resource> iterator = resourceKeyMap.values().iterator();iterator.hasNext();) {
            Resource resource = iterator.next();
            if (resource.getStructNodeId() != null) {
                resourceList.add(resource);
            } else {
                iterator.remove();
            }
        }

使用iterator迭代器,原理就是数据的再一次复制,保证了这个查询过程的连续性。

五、提供完整代码,方便测试

   public static void main(String[] args) {
		Map<String,String> resourceMap = new HashMap<>();
		resourceMap.put("111","111");
		resourceMap.put("222","222");
		resourceMap.put("333","333");
		
		for(Iterator<String> iterator = resourceMap.values().iterator();iterator.hasNext();){
			String resource = iterator.next();
			if(!resource.equals("222")){
				System.out.println(resource);
			}else{
				iterator.remove();
			}
		}
		resourceMap.values().forEach(srting-> System.out.println(srting));
   }

注意:以后触及到删除HahMap的操作,一定要想起迭代器。


THE END

GOOD LUNCK

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值