HashMap中keySet和entrySet的區別
theme: cyanosis
今天進行CR的時候,發現程式碼中對HashMap進行遍歷時,使用的是for(key in map.keys)
,就想起了之前看到的一個文章,說使用entrySet()
進行遍歷效能更高。當時沒有追究,但是最近看《程式碼整潔之道》,學到了
勒布朗(LeBlanc)法則:稍後等於永不(Later equals never)
那麼今天一定要把其中的原理搞清楚。
用法
-
keySet()
for (key in map.keys) { map[key] }
-
entrySet()
for (entry in map.entries) { entry.value }
差異
-
keySet()返回的是一個關於K的Set (第一次查詢),要獲取value,還需要通過map[key]獲取 (第二步查詢)。
-
entrySet()返回的是一個K,V鍵值對的Set (第一次查詢),獲取value直接呼叫entry.value (不需要查詢)。
思考
- 雖然使用
entrySet()
進行遍歷,效能更好,但是多執行緒下就沒辦法保證安全性了,所以在多執行緒情況下,建議考慮使用ConcurrentHashMap()
。 - 觀察
entrySet()
方法,發現entrySet
為null
時,返回的是EntrySet()
物件,但是看EntrySet
原始碼,構造方法是空實現,那資料從哪裡來的呢?先看下原始碼:
```
public Set
final class EntrySet extends AbstractSet``
可以發現
iterator()方法返回了
EntryIterator()物件,深入其中,發現其繼承了
HashIterator,而
HashIterator構造方法則是從關聯到了
table,在
HashMap的put方法中,就是向
table`中插入值。
可能有人會問,這與EntrySet()
有什麼關係呢?for
迴圈怎麼獲取到的Set
物件呢?
通過對kotlin
程式碼轉成Bytecode
,再反編譯成java
語言,可以發現:
```
var3 = map.entrySet().iterator();
while(var3.hasNext()) {
Map.Entry entry = (Map.Entry)var3.next();
entry.getValue();
}
``
就是說
for (entry in map.entries),實際上是遍歷的迭代器,這就與前面
EntrySet的
iterator()`方法的返回值關聯起來了,突然想起了名偵探柯南的畫面,哈哈哈