1. 程式人生 > >【9.0】對於java集合的叠代器的底層分析

【9.0】對於java集合的叠代器的底層分析

trac print post turn pan 很難 分享 對象 nal

前言:如果對java的集合的遍歷(主要是HashMap中的keySet() 和 entrySet()是如何取值並且可以實現遍歷的)不是很明白的話,有興趣深入了解的小夥伴,本文可以作為一個參考,由於時間的原因,就著重講其遍歷的核心代碼,底層叠代器的分析。如果對集合的遍歷已經叠代器沒有基本的理解的話,建議先看看相關的文章;不然很難看懂本文。推薦幾篇相關博文:

1.實在沒想到系列——HashMap實現底層細節之keySet,values,entrySet的一個底層實現細節
2.Java叠代器深入理解及使用
3.Java集合框架中叠代器Iterator解析

由於ArrayList的叠代器實現比較簡單,這裏不贅述,主要講講HashMap的叠代器,以HashMap的entrySet()方法為例:

1.先看一下代碼及其運行結果:

技術分享

如果你點開entrySet()的代碼一看,你就會覺得很神奇,如果你現在無感,那麽你還是先看看這篇博文吧【1.實在沒想到系列——HashMap實現底層細節之keySet,values,entrySet的一個底層實現細節 】(為了方便描述,將該博文稱為博文1,其他類推)。那麽現在分析一下,為什麽entrySet()可以實現將map中值取出來呢,現在按步驟分析如下(以源碼的查看為線索):

1.1 查看HashMap源碼,定位到entrySet()方法:

技術分享

1.2 註意到此處返回的是一個EntrySet對象,那麽定位到EntrySet對象:

技術分享

1.3 這時候你再怎麽深入去定位你都會發現壓根找不到有明顯返回map中的值的地方,具體參考博文1,裏面講得很清楚;然後請註意截圖中紅色圈出的地方,註意到有一個iterator()方法,這就是關鍵所在,這時候請先參考博文2和博文3,以便理解後面的分析。到這裏我們很清楚肯定是map調用了叠代器才使得可以取出map中相關的值(比如Set<Map.Entry<Integer, Integer>> set = map.entrySet();取出值:[1=11, 2=22, 3=33]),但不要誤認為set本身並沒有什麽變量或者字段保存了map中的值,而是在System.out.println(set);的時候,set調用了toString()方法,而toString()方法中調用(循環調用)了iterator()方法,從而遍歷獲取了map中的底層數組table(不懂的自己先查閱資料)中的值,這句話不是很理解沒關系,我們先分析一下EntrySet對象的繼承關系:

final class EntrySet extends AbstractSet<Map.Entry<K,V>> {...}

  

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {...}

  

public abstract class AbstractCollection<E> implements Collection<E> {

....

public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";

StringBuilder sb = new StringBuilder();
sb.append(‘[‘);
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(‘]‘).toString();
sb.append(‘,‘).append(‘ ‘);
}
}

..

}

  

【9.0】對於java集合的叠代器的底層分析