自定义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; } }
核心问题分析
- 泛型声明缺失:类声明
EviatarList implements List, Iterable未指定泛型参数,会导致泛型擦除,引发类型安全问题和编译错误。 - 迭代器共享类状态:使用类级别的
index和iteratorIndex存储迭代器位置,多个迭代器实例同时使用时会互相干扰,导致遍历逻辑混乱。 - hasNext逻辑错误:Iterator的
hasNext方法用index < arr.length && arr[index + 1] != null,既混淆了元素计数和数组长度,又可能引发数组越界;ListIterator的hasNext直接判断index < arr.length,未考虑数组中实际元素的数量。 - next/previous方法状态混乱:ListIterator的
next()和previous()直接操作类的index变量,导致迭代器位置与类的元素计数绑定,完全违背迭代器的独立状态设计。 - 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
相关产品推荐
相关产品推荐

