Java中Iterator(迭代器)的用法及其背后机制的探究
在Java中遍历List时会用到Java提供的Iterator,Iterator十分好用,原因是:
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
只要看看下面这个例子就一清二楚了:
import java.util.*;
public class Muster { public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
Iterator it = list.iterator();
while(it.hasNext()){
String str = (String) it.next();
System.out.println(str);
}
}
}
运行结果:
a
b
c
可以看到,Iterator可以不用管底层数据具体是怎样存储的,都能够通过next()遍历整个List。
但是,具体是怎么实现的呢?背后机制究竟如何呢?
这里我们来看看Java里AbstractList实现Iterator的源代码:
1.public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { // List接口实现了Collection<E>, Iterable<E>
2.
3. protected AbstractList() {
4. }
5.
6. ...
7.
8. public Iterator<E> iterator() {
9. return new Itr(); // 这里返回一个迭代器
10. }
11.
12. private class Itr implements Iterator<E> { // 内部类Itr实现迭代器
13.
14. int cursor = 0;
15. int lastRet = -1;
16. int expectedModCount = modCount;
17.
18. public boolean hasNext() { // 实现hasNext方法
19. return cursor != size();
20. }
21.
22. public E next() { // 实现next方法
23. checkForComodification();
24. try {
25. E next = get(cursor);
26. lastRet = cursor++;
27. return next;
28. } catch (IndexOutOfBoundsException e) {
29. checkForComodification();
30. throw new NoSuchElementException();
31. }
32. }
33.
34. public void remove() { // 实现remove方法
35. if (lastRet == -1)
36. throw new IllegalStateException();
37. checkForComodification();
38.
39. try {
40. AbstractList.this.remove(lastRet);
41. if (lastRet < cursor)
42. cursor--;
43. lastRet = -1;
44. expectedModCount = modCount;
45. } catch (IndexOutOfBoundsException e) {
46. throw new ConcurrentModificationException();
47. }
48. }
49.
50. final void checkForComodification() {
51. if (modCount != expectedModCount)
52. throw new ConcurrentModificationException();
53. }
54. }
55.}
可以看到,实现next()是通过get(cursor),然后cursor++,通过这样实现遍历。
这部分代码不难看懂,唯一难懂的是remove操作里涉及到的expectedModCount = modCount;
在网上查到说这是集合迭代中的一种“快速失败”机制,这种机制提供迭代过程中集合的安全性。
import java.util.*;
public class Muster { public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
Iterator it = list.iterator();
while(it.hasNext()){
String str = (String) it.next();
System.out.println(str);
list.add("s"); //添加一个add方法
}
}
}
运行结果:
a
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at com.hasse.Muster.main(Muster.java:11)
Java中Iterator(迭代器)的用法及其背后机制的探究的更多相关文章
- Java中Iterator(迭代器)实现原理
在Java中遍历List时会用到Java提供的Iterator,Iterator十分好用,原因是: 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结 ...
- Java中的Socket的用法
Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...
- 深入理解Java中的迭代器
迭代器模式:就是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节. 概述 Java集合框架的集合类,我们有时候称之为容器.容器的种类有很多种,比如ArrayList.Li ...
- Java中Iterator类的详细介绍
迭代器模式:就是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节. 概述 Java集合框架的集合类,我们有时候称之为容器.容器的种类有很多种,比如ArrayList.Li ...
- Java中Date各种相关用法
Java中Date各种相关用法(一) 1.计算某一月份的最大天数 Java代码 Calendar time=Calendar.getInstance(); time.clear(); time.set ...
- JAVA中enum的常见用法
JAVA中enum的常见用法包括:定义并添加方法.switch.遍历.EnumSet.EnumMap 1.定义enum并添加或覆盖方法 public Interface Behaviour{ void ...
- 巨人大哥谈Java中的Synchronized关键字用法
巨人大哥谈Java中的Synchronized关键字用法 认识synchronized 对于写多线程程序的人来说,经常碰到的就是并发问题,对于容易出现并发问题的地方价格synchronized基本上就 ...
- Java中Class类及用法
Java中Class类及用法 Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI.这项信息纪录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方 ...
- JAVA中mark()和reset()用法
根据JAVA官方文档的描述,mark(int readlimit)方法表示,标记当前位置,并保证在mark以后最多可以读取readlimit字节数据,mark标记仍有效.如果在mark后读取超过rea ...
随机推荐
- linux的nohup命令的用法。
在应用Unix/Linux时,我们一般想让某个程序在后台运行,于是我们将常会 用 & 在程序结尾来让程序自动运行.比如我们要运行mysql在后台: /usr/local/mysql/bin/m ...
- 30款javascript脚本插件 jquery插件大全
Shifty Nav - a Fully Responsive JS CSS3 Mega Menu Show Demo Shifty Nav is a fully responsive CSS3 ...
- 一个在mac上编译c++程序的低级失误
今天在编译hadoop的pipes的wordcount例子时,总是报错不能成功. g++ -m64 -I/Users/stephen/Downloads/hadoop-0.20.2/c++/Mac_O ...
- javascript数组去重算法-----4
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- mongoose 查询子文档的方法
{ "__v": 1, "_id": "538f5f0f6195a184108c8bd8", "title": &quo ...
- python访问cloudstack的api接口
1.CloudStack API 如同 AWS API 一样,CloudStack API 也是基于 Web Service,可以使用任何一种支持 HTTP 调用的语言(例如 Java,python, ...
- ios webview 加载含有中文的URL网页显示白屏
1. ios中的webview加载的URL不可以含有中文,解决办法说将中文字符转码, 如下: - (NSString *)URLEncodeString { NSCharacterSet *set = ...
- php各类hash算法长度及性能
Hash结果如下 <?php $data = "hello world"; foreach (hash_algos() as $v) { $r = hash($v, $dat ...
- swift论坛正式上线
www.iswifting.com swift论坛正式上线.有问答专区,也有技术分享区,还有学习资料区,大家一起学习成长! 2014中国互联网大会于8月26日开幕. 政府主管部门.行业专家.企业领袖将 ...
- IO与文件读写---使用Apache commons IO包提高读写效率
觉得很不错,就转载了, 作者: Paul Lin 首先贴一段Apache commons IO官网上的介绍,来对这个著名的开源包有一个基本的了解:Commons IO is a library of ...