## 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专题五:持久化