當前位置:首頁 » 存儲配置 » hashmap怎麼存儲

hashmap怎麼存儲

發布時間: 2022-06-27 21:12:07

java中的HashMap的工作原理是什麼

一,存儲方式: Java中的HashMap是以鍵值對(key-value)的形式存儲元素的。


二,調用原理: HashMap需要一個hash函數,它使用hashCode()和equals()方法來向集合/從集合添加和檢索元素。當調用put()方法的時候,HashMap會計算key的hash值,然後把鍵值對存儲在集合中合適的索引上。如果key已經存在了,value會被更新成新值。


三,其他熱性: HashMap的一些重要的特性是它的容量(capacity),負載因子(load factor)和擴容極限(threshold resizing)。

② HashMap如何存儲數據的

對key進行hash,未發生碰撞,直接存儲,發生碰撞,碰撞數小於8,鏈表存儲,大於8,紅黑樹存儲。

參考:

飛升之路 Java學習筆記-HashMap原理

③ C++ Map中的數據存儲方式是什麼Map和HashMap有什麼區別

你要先去了解一下HASH演算法
相對MAP來說,HASHMAP具有更高的查詢速度。
舉個簡單的例子來說
MAP中儲存為順序儲存,也就是一個接著一個的儲存
如一個MAP中存儲
1
3
4
三個元素
則,MAP中第一個元素為1,第二個為3,第三個為4
如果想從MAP中查找元素4,則必須從開始進行便利,則必須比較三次。
而HASHMAP中,開始儲存的時候,就將即將儲存的元素用一個自定義函數將他轉變後,存到相應位置

④ hashmap底層實現原理

hashmap底層實現原理是SortedMap介面能夠把它保存的記錄根據鍵排序,默認是按鍵值的升序排序,也可以指定排序的比較器,當用Iterator遍歷TreeMap時,得到的記錄是排過序的。

如果使用排序的映射,建議使用TreeMap。在使用TreeMap時,key必須實現Comparable介面或者在構造TreeMap傳入自定義的Comparator,否則會在運行時拋出java.lang.ClassCastException類型的異常。

Hashtable是遺留類,很多映射的常用功能與HashMap類似,不同的是它承自Dictionary類,並且是線程安全的,任一時間只有一個線程能寫Hashtable

從結構實現來講,HashMap是:數組+鏈表+紅黑樹(JDK1.8增加了紅黑樹部分)實現的。

(4)hashmap怎麼存儲擴展閱讀

源碼可知,HashMap類中有一個非常重要的欄位,就是 Node[] table,即哈希桶數組。Node是HashMap的一個內部類,實現了Map.Entry介面,本質是就是一個映射(鍵值對),除了K,V,還包含hash和next。

HashMap就是使用哈希表來存儲的。哈希表為解決沖突,採用鏈地址法來解決問題,鏈地址法,簡單來說,就是數組加鏈表的結合。在每個數組元素上都一個鏈表結構,當數據被Hash後,得到數組下標,把數據放在對應下標元素的鏈表上。

如果哈希桶數組很大,即使較差的Hash演算法也會比較分散,如果哈希桶數組數組很小,即使好的Hash演算法也會出現較多碰撞,所以就需要在空間成本和時間成本之間權衡,其實就是在根據實際情況確定哈希桶數組的大小,並在此基礎上設計好的hash演算法減少Hash碰撞。

⑤ 我用一個hashmap存了一個用戶的信息,怎麼把它保存在一個文件里求指點

我採用對象流,對象流就是以對象為單位寫進文件,hashmap集合正好就是一個對象。代碼如下:
/**
* 保存進文件
*/
public static void saveFile() {
try(ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(url)))){
oos.writeObject(list);
System.out.println("保存成功");
} catch (IOException e) {
e.printStackTrace();
}
}
1. try(){}catch只是對異常進行捕獲和關閉對象流,暫時可不必理會,可用eclipse自動生成。
2. new ObjectOutputStream是創建對象流oos;
3. new BufferedOutputStream是創建緩沖流,什麼是緩沖流簡單說下就是跟播放視頻的緩存差不多的道理,可以批量讀寫數據;
4. new FileOutputStream(url)這句代碼才是對文件進行操作,url是你要操作文件的路徑,記住文件路徑這里要用反斜杠/,這句代碼你可以理解成告訴計算機我要對哪個文件進行操作,並分配相應的內存;記住是文件不是文件夾
5. oos.writeObject(list);最後這一句代碼就是把我們的數據從內存寫進文件,看writeObject就知道英文這是對象寫入 操作,list是集合,你可以改成你的map

⑥ 求高手給解答一下 HashMap 的存儲結構,說的越清楚越好,謝謝

HashMap存儲結構淺析
1.hashmap是按照存儲結構來講是數組(散列桶)與鏈表的組合體.

2. 如何計算hashmap中的散列桶的位置。

首先hashcode的值是用來輔助計算散列桶的位置的。如何散列有不同的演算法,比如%或 & (散列桶的length-1)

hashmap內部實現會把hashcode的值通過移位等運算再加工一下,保證加工之後的值二進制串中的01分布更加均勻. 數組的index或散列桶的位置等於h & (length-1); 由於length初始值是16, 將來也是基於2的倍數進行自動擴展. 所以length - 1的binary形式一定是一堆1,然後做與運算的結果就是取優化後哈希值的低位
index一定會<=length-1. 正好做為數組的下標. 注意,通常根據hashcode計算散列桶的演算法是%。
由於數組的長度默認是16,並且會以2的倍數resize,當數組變大之後,會將以前數組中的每個entry的key重新hash到新的數組里:index=h & (newlength-1)

3.與運算會將計算出的哈希值轉換成正的吧?上面有提到過溢出的問題,這樣可能會導致二進制符號位為1,得出的值是負數
->HashMap的代碼實現,裡面的MAX_CAPACITY是Integer Max Value的一半,也就是低位的部分不可能出現在符號位上
注:int是32位,通常最左邊的位是符號位. 如果數組的容量length最大的值才是Integer Max Value的一半,那麼與之後不會肯定影響到符號位的值.

4.字元串如何計算hashcode

for (int i = 0; i < len; i++) {
h = 31*h + val[off++];


}

如果h的值隨著字元串的增長而超過32整型的值.
 不管它如何增大,它只取32位(即使超過32位),所以說會出現負數(超過32位時,32位應該是1. 這樣截取之後,首位是1就會表示負數)。

hashcode的范圍就是一個int的范圍-2^32到2^31

5.

5. 散列的目的是索引化訪問

如果一個map使用array來實現,第一個array裡面存放key,第二個存放value,k-v的index一致。這樣的存儲結構,如果要去匹配某個key,需要遍歷key array的元素,才能找到。這樣查找的效率與array的長度成反比。散列表的出現就是在速度與存儲空間找到一個平衡並且每次查找的時間是恆定的, 散列表的目的就象通過index訪問array那樣,將一切索引化。比如通過hashcode去定位散列桶。散列桶中的元素有可能沖突。hashmap的解決是繼續通過equal去比較沖突的元素是否相等。

又例如hashmap的數組位置是0~7。又假如要把某個類的實例存放在以上8個位置中,如果不用hashcode而任意存放,那麼當查找時就需要到每個位置去找。
假如類中欄位ID,如果hash演算法是hashcode=ID%8,以後在查找該類時就可以通過ID除8 求余數直接找到存放的位置。 

但是如果兩個類的實例的hashcode被散列到同一個桶,例如9除以8和17除以8的余數都是1,這時9和17就存在沖突,這時就需要equals去進一步比較沖突的元素是否相等。

hashcode來定位實例的散列桶位置然後再通過 equals判斷該桶裡面的元素是否邏輯相等。

所以二者的用途一定要區分:equals是用來判斷是否邏輯相等。hashCode是與hashset,hashtable,hashmap之類的數據結構使用時,用來快速定位散列桶。

6.數據結構get/add與hashcode和equal

6.1 HashSet

對於Set介面的實現類HashSet,它是按照哈希演算法來存取集合中的對象,並且因為其繼承了Set介面,所以不允許加入相同的元素,這就要使用到equals()和hashCode()方法了。在往HashSet裡面添加對象的時候,在Add()的方法內部,它首先調用該對象的hashCode()方法,如果返回的哈希碼與集合已存在對象的哈希碼不一致(HashMap會緩存放入元素的hashcode值,方便比較,HashSet有可能一樣,如果存在一樣的hashcode,add失敗,直接返回),則add()方法認定該對象沒有與集合中的其它對象重復,那麼該對象將被添加進集合中。如果hashCode()方法返回的哈希碼與集合已存在對象的哈希碼一致,那麼將調用該對象的equals方法,進一步判斷其是否為同一對象(根據java規范,並不強制不相等的二個對象擁有不相等的hashcode,這樣就導致不相等的二個對象可能存在一樣的hashcode,所以,倒過來,先判斷hashcode相等並不能決定二個對象也一定相等,所以,還需要進一步判斷equal來決定,以便add即使hashcode相同,但是equal不同的元素到hashset里).

6.2 HashMap 具體可以參考effective java 39~40

hashmap的contains方法與get類似,在使用contains之前,先檢查元素的類裡面是否實現了hashcode,equal方法。下面的示例中equal中使用id去判斷是否相等,hashcode裡面一樣,也只能使用id去生成。盡量使hashcode裡面的元素與equal裡面的元素一致。 具體原因可以參考effective java 39~41. 下面示例中直接使用id是因為從第三方調用返回的數據都有id值,並不是需要保存後才會生成id的場景。後一種就不能使用id去判斷了。

@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((m_sId == null) ? 0 : m_sId.hashCode());
return result;
}

@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SNSProfile other = (SNSProfile) obj;
if (m_sId == null)
{
if (other.m_sId != null)
return false;
}
else if (!m_sId.equals(other.m_sId))
return false;
return true;
}

7.String 類的hashcode的生成函數中
for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } 
為什麼要用31×h,這個數字是怎麼算出來的或者說用31有什麼好處
->
這 種方法HashCode的計算方法可能最早出現在Brian W. Kernighan和Dennis M. Ritchie的《The C Programming Language》中,被認為是性價比最高的演算法(又被稱為times33演算法,因為C中乘數常量為33,JAVA中改為31),實際上,包括List在 內的大多數的對象都是用這種方法計算Hash值。 


9.hashmap的容量是按照2的次方增長,所以length-1的二進制值都是1.

8.resize中的transfer方法

void transfer(Entry[] newTable) {
Entry[] src = table;
int newCapacity = newTable.length;
for (int j =0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e !=null) {
src[j] =null;
do {
Entry<K,V> next = e.next;
int i = indexFor(e.hash, newCapacity);
//將newTable[i]的引用(C裡面的指針)賦給了e.next。也就是使用了單鏈表的頭插入方式(還有種是在尾插入方式)
e.next = newTable[i];
newTable[i] = e;//將e插入後做為第一個節點。上一步e.next的指向是舊的第一個節點。
e = next;
} while (e !=null);
}
}
}

HashMap與LinkedHashMap的區別:LinkedHashMap中的key是按照插入的順序排序。不象HashMap的key是無序的。主要用在有序訪問map的場景

⑦ 怎樣利用HashMap類對象存儲一本小型詞典的信息

HashMap是利用 Key - Value(鍵-值對)的方式來存對象的,

這樣,你就可以把 單詞 當作 Key,把注釋當 Value,

因為key是唯一的,這樣就可以根據單詞來取值咯,

取得時候得先判斷一下,看此單詞有沒有存在,否則可能會有空指針異常。

HashMap使用方法,建議你去查看 幫助文檔,我就不再羅嗦了。

⑧ hashmap是以什麼方式存儲數據 arraylist又是以什麼方式存儲數據

hashmap 實質上一個數組和鏈表的結合體,記得嚴尉敏版的C數據結構上將這個稱為「散列表」。對於hashmap存儲可以這樣理解,數組用於存儲key,鏈表用於存儲value,每個鏈表都鏈接在數組中的一個元素上。

arraylist 實質上就是一個順序的動態數組,開始時以一默認值開一數組,滿了後再擴容,且實現了動態添加和刪除。

二者性能區別:hashmpa 用於快速查找,但是arraylist基本上不浪費空間。各有利弊吧

⑨ 怎樣用hashmap保存對象

如果要從hashMap里取數據 當你只取Key時,可以這么做 Iterator ite = keySet.iterator(); while(ite.hasNext()){ System.out.println(ite.next());}只取Value時,這么做 Collection values = hm.values(); ite = values.iterator(); while(ite.hasNext()){ System.out.println(ite.next());}都取出來可以這么做 Set content = hm.entrySet(); ite = content. HashMap map = new HashMap(); map.put('key',obj); 這樣就保存到HashMap里了。

⑩ HashMap是什麼東西

HashMap,中文名哈希映射,HashMap是一個用於存儲Key-Value鍵值對的集合,每一個鍵值對也叫做Entry。這些個鍵值對(Entry)分散存儲在一個數組當中,這個數組就是HashMap的主幹。HashMap數組每一個元素的初始值都是Null。

HashMap是基於哈希表的 Map 介面的實現。此實現提供所有可選的映射操作,並允許使用 null 值和 null 鍵。(除了非同步和允許使用 null 之外,HashMap 類與 Hashtable 大致相同。)此類不保證映射的順序,特別是它不保證該順序恆久不變。

(10)hashmap怎麼存儲擴展閱讀:

因為HashMap的長度是有限的,當插入的Entry越來越多時,再完美的Hash函數也難免會出現index沖突的情況。

HashMap數組的每一個元素不止是一個Entry對象,也是一個鏈表的頭節點。每一個Entry對象通過Next指針指向它的下一個Entry節點。當新來的Entry映射到沖突的數組位置時,只需要插入到對應的鏈表即可。

熱點內容
html文件上傳表單 發布:2024-09-17 03:08:02 瀏覽:783
聊天軟體編程 發布:2024-09-17 03:00:07 瀏覽:725
linuxoracle安裝路徑 發布:2024-09-17 01:57:29 瀏覽:688
兩個安卓手機照片怎麼同步 發布:2024-09-17 01:51:53 瀏覽:207
cf編譯後沒有黑框跳出來 發布:2024-09-17 01:46:54 瀏覽:249
安卓怎麼禁用應用讀取列表 發布:2024-09-17 01:46:45 瀏覽:524
win10設密碼在哪裡 發布:2024-09-17 01:33:32 瀏覽:662
情逢敵手迅雷下載ftp 發布:2024-09-17 01:32:35 瀏覽:337
安卓如何讓軟體按照步驟自動運行 發布:2024-09-17 01:28:27 瀏覽:197
Z包解壓命令 發布:2024-09-17 01:27:51 瀏覽:221