栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java遍历中修改对象——foreach语句的局限性

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java遍历中修改对象——foreach语句的局限性

Java遍历中修改对象——foreach语句的局限性

在lab2中想要实现ConcreteEdgesGraph类的remove方法,使用如下的代码,想在list中进行遍历,查找并删除与某个Vertex(String)相关的Edge。

public class ConcreteEdgesGraph implements Graph {
	private final Set vertices = new HashSet<>();
    private final List> edges = new ArrayList<>();
    //……………………
     
	    @Override public boolean remove(L vertex) {
    	if(vertices.contains(vertex))
    	{
    		vertices.remove(vertex);
    		for(Edge listEdge:edges)
    		{
				if(listEdge.getSource().equals(vertex)||listEdge.getTarget().equals(vertex))
    			{
    				edges.remove(listEdge);
    			}
    			
    		}
    		checkRep();
    		return true;
    	}
    	return false;
        //throw new RuntimeException("not implemented");
    }
    //……………………
}

意为在list中查找到与vertex有关联的Edge listEdge 就直接list调用remove方法在list中删除之。
发现报错,异常类型java.util.ConcurrentModificationException
根据12两篇博客提供的源代码,阅读源码后,总结foreach的机制如下:
1.foreach循环本质上使用java迭代器作为循环工具
2.循环的实现依赖迭代器调用迭代器方法hasNext()与next(),分别判断是否有下一个元素和返回下一个元素并转移至下一元素位置
3.迭代器的实现中引用集合修改次数的变量modCount,创建了自己期望的修改次数变量expectedModCount,初值为modCount。每一轮循环(调用next)都会对两者是否相等进行检查。
4.若使用edges.remove()方法删除list其中一个元素,modCount会+1,exceptedModCount不变,导致异常。(特殊情况,删除倒数第二个元素,由于计数变量curors不变,list 的size因1其remove()而-1,导致两者相等不会进入迭代器的next()方法,继而不会抛出异常。但最后一个元素不会遍历)
据此,解决方法是使用迭代器,并在其中使用迭代器的移除当前元素方法,保证modCount与exceptedModCount在操作后相等。(或者使用for,但就是要避免应用这个foreach)修改代码如下:

public class ConcreteEdgesGraph implements Graph {
	private final Set vertices = new HashSet<>();
    private final List> edges = new ArrayList<>();
    //……………………
     
	    @Override public boolean remove(L vertex) {
    	if(vertices.contains(vertex))
    	{
    		vertices.remove(vertex);
    		//for(Edge listEdge:edges)
    		Iterator> iterator = edges.iterator();
    		while(iterator.hasNext())
    		{
    			Edge listEdge = iterator.next();//变量的作用域
    			if(listEdge.getSource().equals(vertex)||listEdge.getTarget().equals(vertex))
    			{
    				iterator.remove();
    			}
    			
    		}
    		checkRep();
    		return true;
    	}
    	return false;
        //throw new RuntimeException("not implemented");
    }
    //……………………
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/952895.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号