1,定義容器能夠foreach遍歷
2.分析使用Arraylist foreach遍歷時移除數據異常
java容器都具有用於遍歷數據的foreach功能,如果自己定義一個容器類,如何實現這個語法呢?
第一步:實現Iterable接口
實現接口就要實現內部的方法(java8 default修飾的方法無需實現)
public class ForEachClass<T> implements Iterable<T> {
@Override
public Iterator iterator() {
return null;
}
}
第二步:實現接口方法
因爲接口返回iterator對象,所以需要iterator是一個接口,所以必須定義一個實現iterator接口的類,然後實例化後成爲對象再返回.
public class TestForEach {
//注1:T泛型作爲該自定義容器數據的類型
static class ForEachClass<T> implements Iterable<T> {
Object[] value = null;
int current = 0;
//用於測試
public void addvalue(T... t) {
value = t;
}
//注2:每次foreach都會調用該方法
@Override
public Iterator<T> iterator() {
current = 0;
//參考list,用到是new,所以應該沒問題
return new It();
}
注1:這裏Iterable的泛型就是foreach中遍歷數據所對應的類型.
注2:實現Iterable接口
Iterator是一個接口,需要自定義Iterator實現類,實現其hasNext和next方法
private class It implements Iterator<T> {
//注3:是否存在下一個元素,foreach停止的判斷條件
@Override
public boolean hasNext() {
return value != null && current < value.length;
}
//注4:返回一下一個元素,作爲foreach輸出
@Override
public T next() {
T t = (T) value[current];
current++;
return t;
}
}
}
}
注3:是否存在下一個元素,foreach停止的判斷條件
注4:返回一下一個元素,作爲foreach輸出
foreach遍歷
ForEachClass<Integer test = new ForEachClass();
test.addvalue(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for (Integer a : test) {//測試
System.out.print(a + " ");
}
迭代器遍歷數據
當這個容器類可以通過foreach遍歷數據後,這個類也能通過迭代器遍歷數據
Iterator iterator =test.iterator();//注1,上步實現的接口
while(iterator.hasNext()){//注2:上步實現iterator接口的hasNext
Intenger i = iterator.next();//注3:上步實現iterator接口的next
}
}
注1,上步實現的接口
注2:上步實現iterator接口的hasNext
注3:上步實現iterator接口的next
上面3個方法均在實現foreach的時候實現了
foreach中刪除數據報錯
在list中,remove一個數據會導致foreach報ConcurrentModificationException異常
因爲foreach會調用迭代器中next方法,next方法會調用checkForComodification,
public E next() {
checkForComodification();
....
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
因爲list在remove和add的時候會改變modCount的值,expectedModCount只會在foeach開始賦值,在foreach每次調用next都會比較這兩個值,看是否相等,如果不等就報錯.估計設計這個的工程師只想讓foreach只能作爲遍歷數據使用,防止出現其他的bug,畢竟foreach的細節不可見.如果要在遍歷過程中刪除和數據,可以使用迭代器.如下;
Iterator iterator =test.iterator();
while(iterator.hasNext()){
if (iterator.next().equals("3")){
iterator.remove();
}
}
除了容器類可以使用foreach遍歷數據,數組也能通過這種方式遍歷,如:
String[] arg =new String[10];
for(String s:arg) {
///XXXX
}
數組結構比較簡單,而且沒有方法,只有通過length知道大小,通過下標訪問和寫入,編譯器就很輕鬆處理數組的foreach語法.