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

自定义ArrayList实现List接口时Iterator与ListIterator遇错求助

泛型List实现中Iterator与ListIterator的问题

我在课堂上实现了一个类似ArrayList的泛型类,内部是可根据需求自动扩容缩容的数组。现在要实现List接口,但在Iterator和ListIterator的实现上遇到了瓶颈——每次实现依赖这两个迭代器的方法都会报错。已经上网搜索过,但仍有未理清的点。

当前代码实现

public class EviatarList implements List, Iterable {
    private E[] arr;
    private static final int DEFAULT_CAPACITY = 3;
    private int index = 0;

    private int iteratorIndex = 0;

    @Override
    public Iterator<E> iterator() {
        Iterator<E> it = new Iterator<E>() {
            @Override
            public boolean hasNext() {
                return index < arr.length && arr[index + 1] != null;
            }

            @Override
            public E next() {
                return arr[iteratorIndex++];
            }

            @Override
            public void remove() {
                E[] arr1 = (E[]) new Object[size() - 1];
                try {
                    arr[iteratorIndex] = null;
                    iteratorIndex--;
                    index--;
                    for (int i = 0, j = 0; i < arr.length; i++, j++) {
                        if (arr[i] != null) {
                            arr1[j] = arr[i];
                        } else {
                            j--;
                        }
                    }
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                arr = arr1;
            }
        };
        return it;
    }

    public ListIterator<E> listIterator() {
        ListIterator<E> li = new ListIterator<E>() {
            // o(1)
            @Override
            public boolean hasNext() {
                return index < arr.length;
            }

            // o(1)
            @Override
            public E next() {
                return arr[index++];
            }

            // o(1)
            @Override
            public boolean hasPrevious() {
                return index > 0;
            }

            // o(1)
            @Override
            public E previous() {
                return arr[index--];
            }

            // o(1)
            @Override
            public int nextIndex() {
                return iteratorIndex;
            }

            // o(1)
            @Override
            public int previousIndex() {
                return iteratorIndex--;
            }

            // o(n)
            @Override
            public void remove() {
                E[] newArr = (E[]) new Object[arr.length - 1];
                index--;
                for (int i = 0, j = 0; i < index; i++, j++) {
                    if (i != iteratorIndex) {
                        newArr[i] = arr[j];
                    } else {
                        j--;
                    }
                }
                arr = newArr;
            }
        };
        return li;
    }
}

核心问题分析

  1. 泛型声明缺失:类声明EviatarList implements List, Iterable未指定泛型参数,会导致泛型擦除,引发类型安全问题和编译错误。
  2. 迭代器共享类状态:使用类级别的index和iteratorIndex存储迭代器位置,多个迭代器实例同时使用时会互相干扰,导致遍历逻辑混乱。
  3. hasNext逻辑错误:Iterator的hasNext方法用index < arr.length && arr[index + 1] != null,既混淆了元素计数和数组长度,又可能引发数组越界;ListIterator的hasNext直接判断index < arr.length,未考虑数组中实际元素的数量。
  4. next/previous方法状态混乱:ListIterator的next()和previous()直接操作类的index变量,导致迭代器位置与类的元素计数绑定,完全违背迭代器的独立状态设计。
  5. remove方法逻辑错误:两个迭代器的remove方法都存在数组拷贝索引错误、未处理并发修改问题,且未遵循迭代器的remove调用规则(需先调用next()/previous())。

修复方案

1. 修正泛型声明

首先补全类的泛型参数,确保类型安全:

public class EviatarList<E> implements List<E>, Iterable<E> {
    // 原有成员变量和方法保持不变,仅泛型声明补全
}

2. 让迭代器持有独立状态

每个迭代器实例应维护自己的cursor(下一个元素索引)和lastRet(最后访问元素索引),避免共享类状态:

@Override
public Iterator<E> iterator() {
    return new Iterator<E>() {
        private int cursor = 0;
        private int lastRet = -1; // -1表示未调用过next()

        @Override
        public boolean hasNext() {
            return cursor < index; // index是类中记录实际元素数量的变量
        }

        @Override
        public E next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            lastRet = cursor;
            return arr[cursor++];
        }

        @Override
        public void remove() {
            if (lastRet == -1) {
                throw new IllegalStateException();
            }
            // 调用类的remove方法处理元素删除
            EviatarList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
        }
    };
}

3. 实现正确的ListIterator

ListIterator需支持双向遍历,同样使用独立状态变量,并补全所有未实现的方法:

@Override
public ListIterator<E> listIterator() {
    return new ListIterator<E>() {
        private int cursor = 0;
        private int lastRet = -1;

        @Override
        public boolean hasNext() {
            return cursor < index;
        }

        @Override
        public E next() {
            if (!hasNext()) throw new NoSuchElementException();
            lastRet = cursor;
            return arr[cursor++];
        }

        @Override
        public boolean hasPrevious() {
            return cursor > 0;
        }

        @Override
        public E previous() {
            if (!hasPrevious()) throw new NoSuchElementException();
            lastRet = --cursor;
            return arr[cursor];
        }

        @Override
        public int nextIndex() {
            return cursor;
        }

        @Override
        public int previousIndex() {
            return cursor - 1;
        }

        @Override
        public void remove() {
            if (lastRet == -1) throw new IllegalStateException();
            EviatarList.this.remove(lastRet);
            if (lastRet < cursor) {
                cursor--;
            }
            lastRet = -1;
        }

        @Override
        public void set(E e) {
            if (lastRet == -1) throw new IllegalStateException();
            arr[lastRet] = e;
        }

        @Override
        public void add(E e) {
            EviatarList.this.add(cursor, e);
            cursor++;
            lastRet = -1;
        }
    };
}

4. 完善类的基础方法

确保类实现size()、remove(int index)、add(int index, E element)等List接口的核心方法,迭代器的操作依赖这些方法实现,既简化迭代器逻辑,也保证整体功能的一致性。

内容的提问来源于stack exchange,提问作者Eviatar Zilberman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:15:40