## Java專題五:遍歷與迭代
[TOC]
### 5.1.for loop
最常使用的遍歷元素方法,同時可以訪問任意位置的元素,如數組中的a[5]
```java
for (int i=0; i<10; i++){
// do something
}
```
### 5.2.break、continue跳出循環
相當于c語言中goto語句,通常用在循環前面,如下面的`retry:`
**break retry**: 跳出外層循環,直接結束
**continue retry** : 跳出內層循環,進行下一輪循環
```java
// #ThreadPoolExecutor#addWorker(Runnable firstTask, boolean core)
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
```
### 5.3.for-each loop
在Java中能使用for-each語法包括三種情況:
- 數組
- Collection子類
- 自定義類
后2種情況,類必須**實現Iterable接口**。
之所以集合框架中Collection的子類能使用for-each語法對集合元素進行遍歷,是因為Collection接口繼承了Iterable接口`public interface Collection<E> extends Iterable<E>`,并在其子類如ArrayList,Vector等集合類中實現了`iterator()`方法。
**在ArrayList**中就實現了`iterator()`方法:
```java
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
Itr() {}
public boolean hasNext() {
return cursor != size;
}
public E next() {
// ...
}
public void remove() {
// ...
}
}
```
**在HashMap**中,因為HashMap既不是Collection的子類,也沒有實現Iterable接口,選擇了一種迂回方法,先通過`Set<Map.Entry<K,V>> entrySet()`方法將HashMap轉換成可迭代的接口集合,在轉換后的EntrySet中實現實現了`iterator()`方法,同時其元素類型變為為`HashMap.Entry`。
```java
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public final Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
// ...
}
final class EntryIterator extends HashIterator
implements Iterator<Map.Entry<K,V>> {
public final Map.Entry<K,V> next() { return nextNode(); }
}
```
for-each loop語法如下:
```java
for (E e: iterable){
// do something with element of subclass of iterable interface.
}
```
### 5.4.Iterable接口
```java
public interface Iterable<T> {
Iterator<T> iterator();
}
```
### 5.5.Iterator迭代器
類在實現Iterable接口時,必須定義一個實現Iterator接口的內部類。比如前面提到的ArrayList中`Itr`就是`Iterable`接口實現類,然后根據類中的數據結構(在ArrayList中的就是數組)重寫`hasNext()`和`next()`方法。
```java
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
}
```
常見的Iterator迭代用法:
- list和set集合(ArrayList、HashSet等):
```java
for (Iterator it = list.iterator(); it.hasNext();) {
System.out.println(it.next());
}
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
```
- map集合(HashMap、HashSet等):
```java
for (Iterator it = map.iterator(); it.hasNext();) {
System.out.println(it.next().getKey());
System.out.println(it.next().getValue());
}
Iterator it = map.iterator();
while(it.hasNext()){
System.out.println(it.next().getKey());
System.out.println(it.next().getValue());
}
```
### 5.6.Enumeration接口
與Iterator接口功能重復,在設計類時應該優先考慮Iterator接口,因為Iterator接口有更短命名的方法,還增加了remove方法。
```java
public interface Enumeration<E> {
boolean hasMoreElements();
E nextElement();
}
```
**在Hashtable**中使用,也是定義一個實現Enumeration接口的內部類,實現`hasMoreElements()`和`nextElement()`方法。
```java
public synchronized Enumeration<V> elements() {
return this.<V>getEnumeration(VALUES);
}
private <T> Enumeration<T> getEnumeration(int type) {
if (count == 0) {
return Collections.emptyEnumeration();
} else {
return new Enumerator<>(type, false);
}
}
private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
Entry<?,?>[] table = Hashtable.this.table;
int index = table.length;
Entry<?,?> entry;
Entry<?,?> lastReturned;
int type;
boolean iterator;
protected int expectedModCount = modCount;
Enumerator(int type, boolean iterator) {
this.type = type;
this.iterator = iterator;
}
public boolean hasMoreElements() {
// ...
}
public T nextElement() {
// ...
}
// Iterator methods
public boolean hasNext() {
return hasMoreElements();
}
public T next() {
return nextElement();
}
public void remove() {
// ...
}
}
```
- JavaCook
- Java專題零:類的繼承
- Java專題一:數據類型
- Java專題二:相等與比較
- Java專題三:集合
- Java專題四:異常
- Java專題五:遍歷與迭代
- Java專題六:運算符
- Java專題七:正則表達式
- Java專題八:泛型
- Java專題九:反射
- Java專題九(1):反射
- Java專題九(2):動態代理
- Java專題十:日期與時間
- Java專題十一:IO與NIO
- Java專題十一(1):IO
- Java專題十一(2):NIO
- Java專題十二:網絡
- Java專題十三:并發編程
- Java專題十三(1):線程與線程池
- Java專題十三(2):線程安全與同步
- Java專題十三(3):內存模型、volatile、ThreadLocal
- Java專題十四:JDBC
- Java專題十五:日志
- Java專題十六:定時任務
- Java專題十七:JavaMail
- Java專題十八:注解
- Java專題十九:淺拷貝與深拷貝
- Java專題二十:設計模式
- Java專題二十一:序列化與反序列化
- 附加專題一:MySQL
- MySQL專題零:簡介
- MySQL專題一:安裝與連接
- MySQL專題二:DDL與DML語法
- MySQL專題三:工作原理
- MySQL專題四:InnoDB存儲引擎
- MySQL專題五:sql優化
- MySQL專題六:數據類型
- 附加專題二:Mybatis
- Mybatis專題零:簡介
- Mybatis專題一:配置文件
- Mybatis專題二:映射文件
- Mybatis專題三:動態SQL
- Mybatis專題四:源碼解析
- 附加專題三:Web編程
- Web專題零:HTTP協議
- Web專題一:Servlet
- Web專題二:Cookie與Session
- 附加專題四:Redis
- Redis專題一:數據類型
- Redis專題二:事務
- Redis專題三:key的過期
- Redis專題四:消息隊列
- Redis專題五:持久化