You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何声明可保留引用值的ListIterator 解决调用displayNextPhoto的异常问题

问题解决方案

一、迭代器状态保留(解决每次仅展示第一张照片的问题)

你当前问题的根源是每次调用displayNextPhoto方法时,都在方法内部新建了ListIterator实例,迭代器每次都会从列表头部开始遍历,自然每次都返回第一张照片。要保留迭代器的遍历进度,只需将迭代器改为Album类的成员变量,仅在首次调用/需要重置遍历进度时初始化即可。

修改后的代码示例:

Album类新增成员变量

public class Album {
    // 原有成员变量
    private List<Photo> photos;
    private boolean goingForward = false;
    // 新增:存储迭代器实例,保留遍历状态
    private ListIterator<Photo> listIterator;

    // 新增:提供重置遍历进度的方法,需要从头开始看照片时调用即可
    public void resetPhotoIterator() {
        this.listIterator = photos.listIterator();
    }

    // 修改后的displayNextPhoto方法
    public void displayNextPhoto(){
        // 首次调用未初始化时自动创建迭代器
        if(listIterator == null) {
            listIterator = photos.listIterator();
        }
        if(listIterator.hasNext()){
            Photo photo = listIterator.next();
            System.out.println("Displaying "+photo.getName()+" on "+photo.getDate());
            goingForward = true;
        }
        else{
            System.out.println("End of album");
        }
    }
    // 其他原有方法
}

二、并发修改异常解决

ConcurrentModificationException触发的原因是:迭代器创建之后,你在其他代码位置直接修改了photos列表的结构(增/删元素),ArrayList迭代器的fail-fast检测机制就会抛出该异常,可根据你的业务场景选择以下解决方案:

  • 如果遍历期间不需要修改相册列表内容:保证所有对photos的增删操作都在首次调用displayNextPhoto之前完成,或者每次修改完photos列表后主动调用resetPhotoIterator()重置迭代器即可。
  • 如果遍历期间需要修改相册列表内容:不要直接调用photos.add()/photos.remove()方法,改用迭代器自带的listIterator.add()/listIterator.remove()方法修改列表结构。
  • 如果涉及多线程同时操作相册:可以把photos的实现类换成CopyOnWriteArrayList,它的迭代器是快照式实现,不会触发并发修改异常;多线程调用时也可以给操作方法加synchronized同步锁,避免线程安全问题。

注意:如果同时实现了上一张照片的回退逻辑,要注意goingForward变量和迭代器状态的同步,避免出现顺序错乱的问题

内容的提问来源于stack exchange,提问作者محمد المغربى

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 22:54:03