疊代器接口
類圖
疊代器是一個接口, 首先看一下java對疊代器接口的描述資訊,以及這個接口定義的基本規範
疊代器接口的描述, 基本規範
實作這個接口, 允許一個對象成為深度 for - each 的目标。并且能夠使用泛型。
- iterator
- 傳回一個疊代器
- forEach(Consumer<? super T> action)
- 對每一個元素示範提供的動作, 直到所有的元素全部通過或者有一個元素抛出異常, 除非實作類有其他的規定,疊代器将按照順序執行,操作引發的異常被中繼到調用方。
- default
- 在接口中可以使用default關鍵字來修飾一些預設實作的方法。
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
測試
public class test implements Iterable<Integer> {
@Override
public Iterator<Integer> iterator() {
return null;
}
@Override
public void forEach(Consumer<? super Integer> action) {
action.accept(3);
}
@Override
public Spliterator<Integer> spliterator() {
return null;
}
public static void main(String[] args) {
test test = new test();
test.forEach(System.out::println);
}
}
對疊代器簡單探究
ArrayList
疊代器方式
Collection接口也是疊代器接口的子接口, 則其必須對疊代器接口中做出的規範進行實作,下面進行簡單的探究, 在java的集合架構中, 會存在一個簡單的三層模型, 分别是
- 最上層的接口
- 定義規範
- 中間層的抽象類
- 對一些特殊的規範做出統一(或者特殊)的實作
- 最下層的具體實作類
- 根據自己的特電重寫實作類中的實作, 和最上層接口中定義的規則。
對于這三層,将通過ArrayList進行探究, 先看下類圖
- ArrayList 繼承 AbstractList
- AbstractList 繼承 AbstractCollection
- AbstractList 實作 List 接口
- AbstractColleciont 實作 Collection
Collection 接口
我們先看下 Collection 接口中疊代器相關的。幾乎沒有對疊代器接口做出任何的改動, 最上層的接口用來定義規範!
Iterator<E> iterator();
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
AbstractColleciont 實作類
AbstractColleciont 這給抽象類也隻是對 Collection 中的一些普遍方法做出了一些實作,對于疊代器部分也是沒做出修改。
List接口
此接口中又定義了一個ListIterator 的方法, 用作List集合的疊代!
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
AbstractList 實作類
在這個抽象類中終于看到了關于疊代器的部分!可以看到最上層的疊代器方法中傳回了一個疊代器對象!按照内部類的方式進行傳回, 來探究以下其中的方法實作!
- cursor
- 記錄着我們通過疊代器傳回了幾個元素
- lastRet
- 記錄這我們最後一個傳回元素的位置
- expectedModCount
- 我們期望被修改的次數, 用來判斷并發!
- public boolean hasNext()
- 和 cursor 以及 size() 方法一起來判斷是否還有下一個元素
- public E next()
- 傳回下一個元素
- public void remove()
- 删除最近周遊的元素
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
arrayList 類
方法實作上基本和AbstractList 類似, 隻不過多了具體 forEachRemaining(Consumer<? super E> consumer) 的實作, 以及forEach的重寫(重寫的是疊代器接口中預設的實作)
- forEach
- 其中周遊集合中的每一個元素, 對其進行我們的action!
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
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;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
List類
- 疊代器周遊
- for 循環周遊
- forEach周遊
public static void main(String[] args) {
Integer[] ints = {1, 2, 3, 4};
ArrayList<Integer> integers = new ArrayList<Integer>(Arrays.asList(ints));
Iterator<Integer> iterator = integers.iterator();
iterator.next();
iterator.remove();
while (iterator.hasNext()) {
System.out.println("while");
System.out.println("->" + iterator.next());
}
integers.forEach(System.out::println);
for (int i = 0; i < integers.size(); i++) {
System.out.println(integers.get(i));
}
}
Set類
- set.iterator();
- set.toArray();
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<>();
set.add(2);
set.add(3);
set.add(4);
set.add(5);
Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
for (Integer integer : set) {
System.out.println(integer);
}
Object[] toArray = set.toArray();
for (Object o : toArray) {
System.out.println(o);
}
}
Map類
- map.keySet();
- map.values();
- map.entrySet();
public static void main(String[] args) {
HashMap<String, Object> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
Set<Map.Entry<String, Object>> entries = map.entrySet();
for (Map.Entry<String, Object> entry : entries) {
System.out.println(entry.getKey() + "- >" + entry.getValue());
}
Set<String> strings = map.keySet();
for (String string : strings) {
System.out.println(string);
}
Collection<Object> values = map.values();
for (Object value : values) {
System.out.println(value);
}
}