加载dict_Python的dict实现原理和Java的HashMap之间的区别
生活随笔
收集整理的這篇文章主要介紹了
加载dict_Python的dict实现原理和Java的HashMap之间的区别
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Python內(nèi)部很地方都使用著dict這種結(jié)構(gòu),在對象屬性__dict__就是一個字典,所以對其效率要求很高。
dict采用了哈希表,最低能在 O(1)時間內(nèi)完成搜索。同樣的java的HashMap也是采用了哈希表實現(xiàn),不同是dict在發(fā)生哈希沖突的時候采用了開放尋址法,而HashMap采用了鏈接法。
開放尋址法
優(yōu)點
缺點
下面是我根據(jù)自己的理解去用python實現(xiàn)的字典,簡化了很的功能,比如對象緩沖池、String哈希的優(yōu)化等等,如果有錯誤的或者更好的實現(xiàn)方式請指出。因為python沒有純粹的數(shù)組結(jié)構(gòu),所以數(shù)組也是借用list實現(xiàn)的. #python3.6 from collections import namedtupleclass SimpleArray(object):#簡單的數(shù)組類實現(xiàn)def __init__(self, mix):self.container = [None for i in range(mix)]def __len__(self):return len(self.container)def __setitem__(self, key, value):return self.container.__setitem__(key,value)def __getitem__(self, item):return self.container.__getitem__(item)def __delitem__(self, key):return self.container.__setitem__(key, None)def __str__(self):return str(self.container)class SimpleDict(object):#簡單的字典類實現(xiàn)Init_length = 8 # 初始化的大小Load_factor = 2/3 # 擴容因子def __init__(self):self._array_len = SimpleDict.Init_lengthself._array = SimpleArray(self._array_len)self._used = 0self.dictObj = namedtuple("dictObj","key value") # 這里其實可以用數(shù)組也可以的,namedtuple是為了讓代碼更可讀def __getitem__(self, item):key = self._hash(item)dictObj = self._array[key]if dictObj is not None and dictObj.key == item:return dictObj.valueelse:for new_key in self._second_hash(key):if self._array[new_key] is not None and item == self._array[new_key].key:return self._array[new_key].valuedef __setitem__(self, key, value):# 計算是否需要擴容if (self._used / self._array_len) > SimpleDict.Load_factor:self._new_array()#根據(jù)鍵的hash值來計算得出位置索引hash_key = self._hash(key)new_key = self._second_hash(hash_key)while True:if self._array[hash_key] is None or key == self._array[hash_key].key:break# 發(fā)生哈希碰撞根據(jù)二次探查函數(shù)得出下一個索引的位置hash_key = next(new_key)if abs(hash_key) >= self._array_len:self._new_array()hash_key = self._hash(key)# 找到空位將鍵值對象放入self._array[hash_key] = self.dictObj(key, value)self._used += 1def __delitem__(self, key):hash_key = self._hash(key)if key != self._array[hash_key].key:for new_key in self._second_hash(hash_key):if key == self._array[new_key].key:hash_key = new_keyself._array[hash_key] = Noneself._used -= 1def _hash(self, key):# 計算哈希值return hash(key) & (self._array_len-1)def _second_hash(self, hash_key):# 簡單的二次探查函數(shù)實現(xiàn)count = 1for i in range(self._array_len):new_key = hash_key + count**2if abs(new_key) < self._array_len:yield new_keynew_key = hash_key - count**2if abs(new_key) < self._array_len:yield new_keycount += 1def _new_array(self):# 擴容old_array = self._arrayself._array_len = self._array_len * 2 # 擴容2倍大小self._array = SimpleArray(self._array_len)for i in range(len(old_array)):dictObj = old_array[i]if dictObj is not None:self[dictObj.key] = dictObj.valuedef __str__(self):result = ", ".join("%s:%s"%(obj.key, obj.value)for obj in self._arrayif obj is not None)return "{" + result + "}"if __name__ == '__main__':d = SimpleDict()for i in range(20):d[str(i)] = iprint(d)print(d["10"])del d["11"]print(d)
鏈接法
優(yōu)點
缺點
其中有很重要的兩個參數(shù)影響其性能: 初始容量和加載因子
dict:默認初始容量為8,加載因子為2/3
HashMap: 默認初始容量為16, 加載因子為0.75
兩者相同的是擴容的長度必需是2的N次方
總結(jié)
以上是生活随笔為你收集整理的加载dict_Python的dict实现原理和Java的HashMap之间的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信绑不了银行卡怎么办
- 下一篇: 一码通是什么意思?