Java 集合源码解析(2):ListIterator
来源:互联网 发布:怎样在淘宝联盟买东西 编辑:程序博客网 时间:2024/06/02 04:14
ListIterator
根据官方文档介绍, ListIterator 有以下功能:
- 允许我们向前、向后两个方向遍历 List;
- 在遍历时修改 List 的元素;
- 遍历时获取迭代器当前游标所在位置。
注意,迭代器 没有当前所在元素一说,它只有一个游标( cursor )的概念,这个游标总是在元素之间,比如这样:
初始时它在第 0 个元素之前,调用 next() 游标后移一位:
调用 previous() 游标就会回到之前位置。当向后遍历完元素,游标就会在元素 N 的后面:
也就是说长度为 N 的集合会有 N+1 个游标的位置。
ListIterator 继承自 Iterator 接口(关于 Iterator 的介绍 请点这里),在 Iterator 的基础上增加了 6 个方法:
介绍一下新来的几个方法:
- void hasPrevious()
- 判断游标前面是否有元素;
- Object previous()
- 返回游标前面的元素,同时游标前移一位。游标前没有元素就报 java.util.NoSuchElementException 的错,所以使用前最好判断一下;
- int nextIndex()
- 返回游标后边元素的索引位置,初始为 0 ;遍历 N 个元素结束时为 N;
- int previousIndex()
- 返回游标前面元素的位置,初始时为 -1,同时报 java.util.NoSuchElementException 错;
- void add(E)
- 在游标 前面 插入一个元素
- 注意,是前面
- void set(E)
- 更新迭代器最后一次操作的元素为 E,也就是更新最后一次调用 next() 或者 previous() 返回的元素。
- 注意,当没有迭代,也就是没有调用 next() 或者 previous() 直接调用 set 时会报 java.lang.IllegalStateException 错;
- void remove()
- 删除迭代器最后一次操作的元素,注意事项和 set 一样。
ListIterator 有两种获取方式
- List.listIterator()
- List.listIterator(int location)
区别在于第二种可以指定 游标的所在位置。
ListIterator 的具体实现?
AbstractList 作为 List 的直接子类,里面实现了 listIterator() 方法,并且有两个内部迭代器实现类:SimpleListIterator,FullListIterator:
listIterator() 返回的是 FullListIterator():
FullListIterator 继承了 SimpleListIterator, SimpleListIterator 实现了 Iterator 接口:
private class SimpleListIterator implements Iterator<E> { //游标的位置,初始为 -1 int pos = -1; //用来判断是否 fail-fast 的变量 int expectedModCount; //记录上次迭代的位置 int lastPosition = -1; SimpleListIterator() { expectedModCount = modCount; } //当游标没有跑到最后一个元素后面时 hasNext 返回 true public boolean hasNext() { return pos + 1 < size(); } //获取下一个元素 public E next() { if (expectedModCount == modCount) { try { //获取游标后面的元素,具体子类有具体实现 E result = get(pos + 1); //更新 lastPosition = ++pos; return result; } catch (IndexOutOfBoundsException e) { throw new NoSuchElementException(); } } //当迭代时修改元素,就会报这个错,上篇文章介绍过解决办法~ throw new ConcurrentModificationException(); } //删除上次迭代操作的元素 public void remove() { //还没进行迭代操作就会报这个错 if (this.lastPosition == -1) { throw new IllegalStateException(); } if (expectedModCount != modCount) { throw new ConcurrentModificationException(); } try { //调用子类实现的删除操作 AbstractList.this.remove(lastPosition); } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } expectedModCount = modCount; if (pos == lastPosition) { pos--; } //每次删除后都会还原为 -1,也就是说我们迭代一次后只能 remove 一次,再 remove 就会报错 lastPosition = -1; }}
了解了 SimpleListIterator 后我们看下 FullListIterator 的具体实现:
private final class FullListIterator extends SimpleListIterator implements ListIterator<E> { //根据 start 指定游标位置 FullListIterator(int start) { if (start >= 0 && start <= size()) { pos = start - 1; } else { throw new IndexOutOfBoundsException(); } } //在游标前面添加元素 public void add(E object) { if (expectedModCount == modCount) { try { //调用子类的添加操作,ArrayList, LinkedList,Vector 的添加操作实现有所不同 AbstractList.this.add(pos + 1, object); } catch (IndexOutOfBoundsException e) { throw new NoSuchElementException(); } //游标后移一位 pos++; //!注意! 添加后 上次迭代位置又变回 -1 了,说明 add 后调用 remove, set 会有问题! lastPosition = -1; if (modCount != expectedModCount) { expectedModCount = modCount; } } else { throw new ConcurrentModificationException(); } } //当游标不在初始位置(-1)时返回true public boolean hasPrevious() { return pos >= 0; } //游标后面的元素索引,就是游标 +1 public int nextIndex() { return pos + 1; } //游标前面一个元素 public E previous() { if (expectedModCount == modCount) { try { E result = get(pos); lastPosition = pos; pos--; return result; } catch (IndexOutOfBoundsException e) { throw new NoSuchElementException(); } } throw new ConcurrentModificationException(); } //游标前面元素的索引,就是游标的位置,有点晕的看开头那几张图 public int previousIndex() { return pos; } //更新之前迭代的元素为 object public void set(E object) { if (expectedModCount == modCount) { try { //调用子类的set AbstractList.this.set(lastPosition, object); } catch (IndexOutOfBoundsException e) { throw new IllegalStateException(); } } else { throw new ConcurrentModificationException(); } }}
可以看到 SimpleListIterator 的主要操作最后都交给子类来实现,List 的子类 ArrayList, LinkedList, Vector 由于底层实现原理不同(数组,双向链表),具体操作类实现有所不同。
等接下来分析到具体子类再看相关实现吧。
阅读全文
0 0
- Java 集合源码解析(2):ListIterator
- Java 集合源码解析(2):ListIterator
- Java 集合源码解析(2):ListIterator
- Java集合分析(2):ListIterator
- 解析java.util集合类源码(AbstractList内部类ListIterator和Itr)
- java 集合 ListIterator
- java 集合框架之LinkedList及ListIterator实现源码分析
- 集合框架(ListIterator)
- java集合之迭代器ListIterator
- [疯狂Java]集合:List、ListIterator
- Java 集合框架listIterator接口
- Java集合源码解析(一)ArrayList源码解析
- Java集合源码解析(二)HashMap源码解析
- Java集合源码解析(三)HashMap源码解析
- Java集合源码解析(四)TreeMap源码解析
- Java集合源码解析(五)HashSet源码解析
- 一步一步解析java集合框架HashMap源码(2)
- java集合类源码解析(2)---ArrayList
- JAVA经典面试题(来源于互联网)
- hasOwnProperty实现数组去重
- 阿里菜鸟网络二面
- Unity图片优化神器
- 广播实时监听网络状态
- Java 集合源码解析(2):ListIterator
- app declares a dependency from configuration 'compile' to configuration 'default' which is not decla
- Spring Boot 集成 resteasy篇 — jax-rs初步介绍和spring boot集成
- Carbon Data 字典编码
- Flip Game POJ
- ??运算符
- Java中的Filter过滤器
- iOS ATS测试跳过无效证书
- jedis总结