Iteration ist für diejenigen von uns, die in Java arbeiten, definitiv nicht unbekannt. Wir verwenden häufig die von JDK bereitgestellte Iterationsschnittstelle, um Java-Sammlungen zu iterieren.
Iterator iterator = list.iterator(); while(iterator.hasNext()){ String string = iterator.next(); //do something }
Tatsächlich können wir Iteration einfach verstehen as Traversal ist eine standardisierte Methodenklasse zum Durchlaufen aller Objekte in verschiedenen Containern. Es handelt sich um ein sehr typisches Entwurfsmuster. Das Iteratormuster ist die Standardzugriffsmethode zum Durchlaufen von Sammlungsklassen. Es kann die Zugriffslogik von verschiedenen Arten von Sammlungsklassen abstrahieren und so vermeiden, dass die interne Struktur der Sammlung dem Client offengelegt wird. So machen wir es, wenn keine Iteratoren vorhanden sind. Wie folgt:
Für Arrays verwenden wir Indizes zur Verarbeitung:
int[] arrays = new int[10]; for(int i = 0 ; i < arrays.length ; i++){ int a = arrays[i]; //do something }
So wird ArrayList behandelt:
List<String> list = new ArrayList<String>(); for(int i = 0 ; i < list.size() ; i++){ String string = list.get(i); //do something }
Es gibt keine Möglichkeit, die Zugriffslogik von Sammlungsklassen und Clientcode zu trennen. Gleichzeitig entspricht jede Sammlung einer Traversierungsmethode und der Clientcode kann nicht wiederverwendet werden. In praktischen Anwendungen ist es ziemlich mühsam, die beiden oben genannten Sätze zu integrieren. Um die oben genannten Probleme zu lösen, wurde der Iterator-Modus entwickelt. Er verwendet immer dieselbe Logik, um die Sammlung zu durchlaufen. Der Client selbst muss die interne Struktur der Sammlung nicht verwalten, und alle internen Zustände werden von Iterator verwaltet. Der Client befasst sich nie direkt mit der Sammlungsklasse. Er steuert immer den Iterator und sendet ihm die Befehle „Vorwärts“, „Rückwärts“ und „Aktuelles Element abrufen“, um indirekt die gesamte Sammlung zu durchlaufen.
Das Obige ist nur eine kurze Erklärung des Iterator-Modus. Werfen wir einen Blick auf die Iterator-Schnittstelle in Java, um zu sehen, wie sie implementiert ist.
In Java ist Iterator eine Schnittstelle, die nur Iteration bereitstellt Grundregeln sind im JDK wie folgt definiert: ein Iterator, der die Sammlung durchläuft. Iteratoren ersetzen die Enumeration im Java Collections Framework. Es gibt zwei Unterschiede zwischen Iteratoren und Aufzählungen:
Element entfernen.
2. Der Methodenname wurde verbessert.
Die Schnittstelle ist wie folgt definiert:
public interface Iterator { boolean hasNext(); Object next(); void remove(); }
Wobei:
Object next(): Gibt einen Verweis auf das gerade gekreuzte Element zurück vom Iterator. Der Rückgabewert ist Object, das in den von Ihnen benötigten Typ umgewandelt werden muss
void remove(): Entfernen Sie das Element, das gerade vom Iterator gekreuzt wurde
Für uns müssen wir im Allgemeinen nur die Methoden next() und hasNext() verwenden, um Vervollständigen Sie die Iteration. Wie folgt:
前面阐述了Iterator有一个很大的优点,就是我们不必知道集合的内部结果,集合的内部结构、状态由Iterator来维持,通过统一的方法hasNext()、next()来判断、获取下一个元素,至于具体的内部实现我们就不用关心了。但是作为一个合格的程序员我们非常有必要来弄清楚Iterator的实现。下面就ArrayList的源码进行分析分析。
下面就ArrayList的Iterator实现来分析,其实如果我们理解了ArrayList、Hashset、TreeSet的数据结构,内部实现,对于他们是如何实现Iterator也会胸有成竹的。因为ArrayList的内部实现采用数组,所以我们只需要记录相应位置的索引即可,其方法的实现比较简单。
在ArrayList内部首先是定义一个内部类Itr,该内部类实现Iterator接口,如下:
private class Itr implements Iterator<E> { //do something }
而ArrayList的iterator()方法实现:
public Iterator<E> iterator() { return new Itr(); }
所以通过使用ArrayList.iterator()方法返回的是Itr()内部类,所以现在我们需要关心的就是Itr()内部类的实现:
在Itr内部定义了三个int型的变量:cursor、lastRet、expectedModCount。其中cursor表示下一个元素的索引位置,lastRet表示上一个元素的索引位置
int cursor; int lastRet = -1; int expectedModCount = modCount;
从cursor、lastRet定义可以看出,lastRet一直比cursor少一所以hasNext()实现方法异常简单,只需要判断cursor和lastRet是否相等即可。
public boolean hasNext() { return cursor != size; }
对于next()实现其实也是比较简单的,只要返回cursor索引位置处的元素即可,然后修改cursor、lastRet即可,
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; //cursor + 1 return (E) elementData[lastRet = i]; //lastRet + 1 且返回cursor处元素 }
checkForComodification()主要用来判断集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过。在java提高篇(二一)-----ArrayList中已经阐述了。modCount用于记录ArrayList集合的修改次数,初始化为0,,每当集合被修改一次(结构上面的修改,内部update不算),如add、remove等方法,modCount + 1,所以如果modCount不变,则表示集合内容没有被修改。该机制主要是用于实现ArrayList集合的快速失败机制,在Java的集合中,较大一部分集合是存在快速失败机制的,这里就不多说,后面会讲到。所以要保证在遍历过程中不出错误,我们就应该保证在遍历过程中不会对集合产生结构上的修改(当然remove方法除外),出现了异常错误,我们就应该认真检查程序是否出错而不是catch后不做处理。
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
对于remove()方法的是实现,它是调用ArrayList本身的remove()方法删除lastRet位置元素,然后修改modCount即可。
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(); } }
这里就对ArrayList的Iterator实现讲解到这里,对于Hashset、TreeSet等集合的Iterator实现,各位如果感兴趣可以继续研究,个人认为在研究这些集合的源码之前,有必要对该集合的数据结构有清晰的认识,这样会达到事半功倍的效果!!!!
————————————————————————————— ———————— ————————————
Das Obige ist der Java-Verbesserungsartikel (Teil 3 10) -- ---Für den Inhalt von Iterator beachten Sie bitte die chinesische PHP-Website (m.sbmmt.com), um weitere verwandte Inhalte zu erhalten!