java迭代器浅析
来源:互联网 发布:剑灵龙族男捏脸数据 编辑:程序博客网 时间:2024/06/08 16:55
迭代器是遍历容器的一种常用方法,它屏蔽了容器的实现细节,无需暴露数据结构内部,就可以对容器进行遍历,迭代器本身也是一种设计模式,迭代是一种特殊的遍历方式
Iterator
在java中,迭代器接口Iterator定义了三种方法
public interface Iterator<E> { // 是否还有元素可以迭代,如果有 返回true 没有返回false boolean hasNext(); // 返回迭代的下一个元素 E next(); // 从迭代器指向的 collection 中移除迭代器返回的最后一个元素 void remove();}
remove方法是移除迭代器返回的最后一个元素,因此如果没有调用过next方法,直接调用remove方法是错误的做法,并且每执行一次next方法,只能调用一次remove方法
Iterable
Iterable只有一个iterator方法,该方法会返回一个迭代器,一般情况下使用迭代器的类都会实现Iterable接口而非直接实现Iterator接口
public interface Iterable<T> { // 返回一个在一组 T 类型的元素上进行迭代的迭代器。 Iterator<T> iterator();}
foreach 就是对迭代器的另外一种使用方式,只要是实现Iterable接口的类,就可以用foreach对自身进行遍历
map 迭代
map接口并未继承Iterable接口,因此本身并不能直接使用迭代器,不过可以转化为collection然后进行迭代,例如:
Map<String, String> map = new HashMap<>();map.put("韦德", "35");Iterator<Entry<String, String>> iterator = map.entrySet().iterator();while (iterator.hasNext()) { Entry<String, String> entry = iterator.next(); System.out.println(entry.getKey() + ":" + entry.getValue());}
map的遍历方式可参考 java中遍历Map的几种方法
collection 迭代
collection接口继承了Iterable接口,因此只要是collection实例,都可以使用迭代器进行遍历
Collection<String> collection = Arrays.asList("java", "c", "js");Iterator<String> iterator = collection.iterator();while (iterator.hasNext()) { String str = iterator.next(); System.out.println(str);}
用迭代器遍历collection的优势在于遍历的过程中可以remove元素,用foreach则不行
ListIterator
ListIterator是对Iterator的扩展,针对定义了ListIterator方法的有序的容器,可以采用ListIterator进行迭代,ListIterator新增了一些方法,可以在遍历时获取数据的索引,或者逆序遍历等。
public interface ListIterator1<E> extends Iterator<E> { // 是否还有上一个元素 一般逆序遍历时使用 boolean hasPrevious(); // 返回列表中的上一个元素 E previous(); // 返回对 next 的后续调用所返回元素的索引。(如果列表迭代器在列表的结尾,则返回列表的大小) int nextIndex(); // 返回对 previous 的后续调用所返回元素的索引。(如果列表迭代器在列表的开始,则返回 -1) int previousIndex(); // 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。只有在最后一次调用 next 或 previous // 后既没有调用 ListIterator.remove 也没有调用 ListIterator.add 时才可以进行该调用。 void set(E e); // 将指定的元素插入列表(可选操作)。该元素直接插入到 next 返回的下一个元素的前面(如果有) //或者 previous 返回的下一个元素之后(如果有); void add(E e); // ... Iterator methods}
List提供了两个重载的listIterator方法,可以通过这两个方法拿到一个ListIterator对象
public interface List1<E> extends Collection<E> { // 此列表元素的列表迭代器 ListIterator<E> listIterator(); // 此列表元素的列表迭代器 可以指定一个参数index // index 从列表迭代器返回的第一个元素的索引(通过调用 next 方法) ListIterator<E> listIterator(int index); // List other methods}
使用listIterator对List进行逆序遍历
List<String> list = Arrays.asList("java", "c", "js");ListIterator<String> listIterator = list.listIterator(list.size());while (listIterator.hasPrevious()) { System.out.println("前一个元素索引为:" + listIterator.previousIndex()); System.out.println("前一个元素为:" + listIterator.previous());}
光标(cursor)
迭代器没有当前元素的概念,但有光标(cursor)的概念,
如果不指定光标的位置,光标默认在第一个元素之前,此时如果调用next方法,光标会跳到第一个元素和第二个元素中间,并且返回第一个元素
ListIterator<String> listIterator = list.listIterator(list.size());
以上代码,指定了光标的位置,在最后一个元素的后面,此次要调用next方法会抛异常,因为没有下一个元素,如果调用nextIndex则会返回容器长度,调用previous则返回最后一个元素,同时光标向上移动一位
总结
迭代器在使用的过程中其实还有诸多限制,如果使用不当,很可能出现死循环,抛异常等问题,例如:如果在用ListIterator逆序遍历的时候新增,会造成死循环。
因此在学习迭代器的时候,不仅要掌握其使用方法,还要明白其实现原理。看源码是不错的学习办法,有兴趣的可以看看Collection的众多实现类对迭代的实现。
- java迭代器浅析
- java 浅析
- 浅析 Java 中的覆盖
- JAVA 的多线程浅析
- JAVA 的多线程浅析
- Java范型浅析
- 浅析Java泛型
- Java范型浅析
- 浅析JAVA内部类
- JAVA 的多线程浅析
- JAVA 的多线程浅析
- Java数组浅析
- 浅析 Java Thread.join()
- Java数据类型转换-浅析
- Java IO操作浅析
- JAVA 的多线程浅析
- JAVA 的多线程浅析
- 浅析 Java Thread.join()
- 单向链表的基本操作
- JavaScript-定时器的使用之无缝滚动
- MyBatis传入参数的问题
- Python Requests Libraries
- 迭代器 生成器
- java迭代器浅析
- Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo 矩阵快速幂+dp
- 字体图标使用方法——以Iconfont为例
- Lintcode翻转链表
- onclick="function()"和onclick="return function();"区别
- Android OpenGLES2.0(十八)——轻松搞定Blend颜色混合
- UVA 11149
- Excel导出简单例子
- [leetcode]52. N-Queens II