老师,我这里使用老师的方法使用增强型for循环,但是出现了程序异常ConcurrentModificationException,请问这个是哪里导致的呢?

老师,我这里使用老师的方法使用增强型for循环,但是出现了程序异常ConcurrentModificationException,请问这个是哪里导致的呢?

老师,我这里使用老师的方法使用增强型for循环,但是出现了程序异常ConcurrentModificationException,请问这个是哪里导致的呢?

package com.imooc.set;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class CatTest {
    public static void main(String[] args){
        //定义宠物猫对象
        Cat huahua = new Cat("花花",12,"英国短毛猫");
        Cat fanfan = new Cat("凡凡",3,"中华田园猫");
        //Set类中使用泛型
        Set <Cat> set = new HashSet<Cat>();//泛型实在javaSE5.0以后引入的概念,5.0之前没有泛型的概念,我们通过对类型Object的引用来实现参数的任意化,任意化带来的缺点是要做显示的强制类型转换
        set.add(huahua);
        set.add(fanfan);
        //显示宠物猫信息,迭代器接口中使用泛型
        Iterator <Cat> it = set.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        //我们如果不在宠物猫类中写入toString方法,那么迭代器返回的值就是内存地址,如果写入了toString,那么就会自动调用toString方法
        //再添加一个与花花属性一样的猫
        Cat huahua01 = new Cat("花花",12,"英国短毛猫");//重写hashCode方法和equals方法后,则重复值可以消失
        set.add(huahua01);
        System.out.println("*****************************");
        System.out.println("添加重复数据后的宠物猫信息:");
        it=set.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        System.out.println("*****************************");
        //重新插入一个新的宠物猫
        Cat huahua02 = new Cat("花花二代",2,"英国短毛猫");
        set.add(huahua02);
        System.out.println("添加花花二代后的宠物猫信息" );
        it=set.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        System.out.println("*****************************");
        //在集合中查找花花的信息并且输出:这里其实有多种查找方式,对象名?还是通过哪一个属性去查找这一条记录?
        if(set.contains(huahua)){//contains方法可以用于判断集合中是否存在花花这个对象
            System.out.println("花花找到了!");
            System.out.println(huahua);
        }else {
            System.out.println("花花没找到!");
        }
        //如果我们不知道huahua这个对象,只知道“花花”这个名字,该如何查找
        //还是需要遍历我们的集合,定义一个布尔变量来进行是否找到的判断
        System.out.println("*****************************");
        System.out.println("通过名字查找花花的信息");
        boolean flag = false;
        Cat c = null;
        it = set.iterator();
        while (it.hasNext()){//我们的思路就是遍历集合,从集合中取出Cat元素,把它的名字挨个与花花进行比较
           c = it.next();//由于next方法得到的是object类型的对象,所以这里我们需要进行强制类型转换转换成我们所需要的Cat类型,这里有一个问题,就是我们必须知道next()方法取出的值一定是Cat类型的才能进行强转,否则有可能会报错。这里我们使用了泛型,所以无需使用强制类型转换
            //假设我们把前后都加上String类型,那么就会产生类型转换异常,解决方式就是引入泛型,加入泛型之后就不需要进行强制转换了,泛型就限定了在集合中添加的数据必须是我们所需要的类型。泛型的语法格式,再类或接口后面写一个尖括号,在尖括号中写入需要往集合中添加的元素到底是什么类型进行限制
            if (c.getName().equals("花花")){
                flag = true;//这就说明找到了
                break;
            }
        }
        if (flag){
            System.out.println("花花找到了");
            System.out.println(c);
        }else {
            System.out.println("花花没找到");
        }
        //如何在hashset中删除元素,删除花花二代的信息并重新输出,引入泛型以后,我们除了迭代器以外,还可以使用增强型for循环来遍历集合
        for (Cat cat:set){
            if ("花花二代".equals(cat.getName())){
                set.remove(cat);
            }
        }
        System.out.println("*****************************");
        System.out.println("删除花花二代后的数据");
        for (Cat cat:set){
            System.out.println(cat);
        }
    }
}
[姓名:花花, 年龄:12, 品种:英国短毛猫]
[姓名:凡凡, 年龄:3, 品种:中华田园猫]
*****************************
添加重复数据后的宠物猫信息:
[姓名:花花, 年龄:12, 品种:英国短毛猫]
[姓名:凡凡, 年龄:3, 品种:中华田园猫]
*****************************
添加花花二代后的宠物猫信息
[姓名:花花, 年龄:12, 品种:英国短毛猫]
[姓名:花花二代, 年龄:2, 品种:英国短毛猫]
[姓名:凡凡, 年龄:3, 品种:中华田园猫]
*****************************
花花找到了!
[姓名:花花, 年龄:12, 品种:英国短毛猫]
*****************************
通过名字查找花花的信息
花花找到了
[姓名:花花, 年龄:12, 品种:英国短毛猫]
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
	at java.util.HashMap$KeyIterator.next(HashMap.java:1466)
	at com.imooc.set.CatTest.main(CatTest.java:70)

Cat类的编写如下:

package com.imooc.set;

import java.util.Objects;

public class Cat {
    private String name;//名字
    private int month;//年龄
    private String species;//品种

    public Cat(String name, int month, String species) {
        super();
        this.name = name;
        this.month = month;
        this.species = species;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public String getSpecies() {
        return species;
    }

    public void setSpecies(String species) {
        this.species = species;
    }

    @Override
    public String toString() {
        return "[姓名:" + name +  ", 年龄:" + month + ", 品种:" + species + ']';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;//对象相等就不需要比较内容了
        if (o == null || getClass() != o.getClass()) return false;//判断obj是否是Cat类的对象,如果不是或者对象为null则返回false

        Cat cat = (Cat) o;//是的话,强制转换对象类型
        //接下来逐一比较对象属性
        if (month != cat.month) return false;
        if (!name.equals(cat.name)) return false;
        return species.equals(cat.species);
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + month;
        result = 31 * result + species.hashCode();
        return result;
    }
}

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学你好,ConcurrentModificationException异常通常出现在使用增强for循环遍历集合的同时,对集合中的元素进行了删除导致的。这也是实际开发时非常容易出现的小错误,同学需要牢记,当需要遍历的同时对集合中的元素进行增加或者删除操作时,千万不要使用增强for循环。

实际上,使用迭代器Iterator不容易出现这个问题,所以可以选用Iterator,需要注意的是,移除元素时需要使用迭代器的移除方法,否则也会抛出异常。另外,使用一般for循环时,由于增和删的操作可能会导致元素下标的移位,所以也不是很适合。

一般遇到这样的问题,我们会选择另外一种处理方案:声明一个同类型的空集合,将满足条件的元素添加到新集合中,然后将新集合覆盖到原集合的变量中。这样相当于变相的完成了筛选删除的操作,并且不会触发任何异常或者错误。

祝学习愉快~

  • 慕容2472778 提问者 #1

    谢谢老师的解答

    2023-11-08 14:29:00
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
计算机基础课
  • 参与学习       244    人
  • 解答问题       162    个

1000位程序员+大厂HR联袂推荐,面向所有程序员的计算机核心知识体系,优惠中~

了解课程
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师