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()將迭代器新返回的元素刪除。
只要看看下面這個例子就一清二楚了:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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;
在網上查到說這是集合迭代中的一種“快速失敗”機制,這種機制提供迭代過程中集合的安全性。
從原始碼裡可以看到增刪操作都會使modCount++,通過和expectedModCount的對比,迭代器可以快速的知道迭代過程中是否存在list.add()類似的操作,存在的話快速失敗! 在第一個例子基礎上新增一條語句: ?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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中遍歷List時會用到Java提供的Iterator,Iterator十分好用,原因是:
迭代器是一種設計模式,它是一個物件,它可以遍歷並選擇序列中的物件,而開發人員不需要了解該序列的底層結構。迭代器通常被稱為“輕量級”物件,因為建立它的代價小。
Java中的Iterator功能比較簡單,並且只能單向移動:
(1) 使用方法iterator()要求容器返回一個Iterator。第一次呼叫Iterator的next()方法時,它返回序列的第一個元素。注意:iterator()方法是java.lang.Iterable介面,被Collection繼承。
(2) 使用next()獲得序列中的下一個元素。
(3) 使用hasNext()檢查序列中是否還有元素。
(4) 使用remove()將迭代器新返回的元素刪除。
只要看看下面這個例子就一清二楚了:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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;
在網上查到說這是集合迭代中的一種“快速失敗”機制,這種機制提供迭代過程中集合的安全性。
從原始碼裡可以看到增刪操作都會使modCount++,通過和expectedModCount的對比,迭代器可以快速的知道迭代過程中是否存在list.add()類似的操作,存在的話快速失敗! 在第一個例子基礎上新增一條語句: ?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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)