按域名瀏覽

HASHMAP在JAVA -你需要知道的一切

介紹

在Java中,您可能聽說過Map接口(它擴展了Collection接口)。有一些映射接口的實現類,其中一個這樣的類是HashMap(在java。跑龍套包)。表示為HashMap < K、V >K代表鍵,V代表值。簡單來說,HashMap < K、V >是一種數據結構,以鍵值對的形式存儲元素。這些鍵值對也稱為鍵值對條目HashMap。鍵是唯一的,不允許重複的鍵。它基於鍵存儲值,並且可以使用鍵訪問它。Hashmap允許多個空值和一個空鍵。

hashmap是非同步的,這意味著它們不是線程安全的。如果多個線程同時訪問hashmap,它們將在結構上修改該映射。hashmap是鍵值對的無序集合。它們不維護插入順序。與數組和鏈表相比,它們在檢索數據方麵要快得多,基本操作具有恒定的時間性能。hashmap的初始默認容量(可以存儲的元素數量)是16,默認負載因子是0.75。在後麵幾節中,我們將討論容量和負載因子。

層次結構

檢查上麵的層次圖;HashMap類擴展了AbstractMap類並實現了Map、Serializable和clone接口。

檢查上麵的層次圖;HashMap類擴展了AbstractMap類並實現了Map、Serializable和clone接口。

Hashmap類的聲明:

公共類HashMap擴展了AbstractMap實現了Map,可克隆,可序列化

K:密鑰類型

V:值的類型

還要檢查Java初學者教程| Java概述

hashmap中的構造函數

hashmap有四個構造函數,它們都有公共訪問說明符。

1.Hashmap ()

它是創建初始容量為的hashmap實例的默認構造函數

16,負載係數0.75。

HashMap hm = new HashMap();//實例創建

演示默認Hashmap構造函數的程序:
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);}}

輸出{紅色=1,藍色=2,黃色=4,綠色=3}[插入順序不保留

2.HashMap (int initialCapacity)

此構造函數創建一個具有指定初始容量和的hashmap實例

默認負載係數0.75。

HashMap hm = new HashMap(int initialCapacity);//實例創建

演示Hashmap構造函數的程序:
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap (5);hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);}}

輸出:{紅色=1,藍色=2,黃色=4,綠色=3}

3.HashMap(int initialCapacity, float loadFactor)

方法創建具有指定初始容量的hashmap實例

指定的負載因數。

HashMap hm = new HashMap(int initialcapacity, float loadfactor);

演示Hashmap構造函數的程序:
進口. io . *;進口java.util。*;public class Hashmap {public static void main(String args[]) {Hashmap  hm = new Hashmap (5,0.75f);hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);}}

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

4.HashMap(地圖地圖)

這個構造函數創建一個hashmap實例,其映射與給定Map類似。

HashMap hm =新的HashMap(Map m);/ /實例創建

演示Hashmap構造函數的程序:
進口. io . *;進口java.util。*;public class Hashmap {public static void main(String args[]) {Map hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);HashMap hm1 = new HashMap(hm);System.out.println (hm1); } }

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

{紅色=1,藍色=2,黃色=4,綠色=3}

hashmap的操作

hashmap包括基本操作,如添加、獲取、更新和刪除元素,就像任何其他數據結構一樣。基本操作如下:

1.添加元素

要在Hashmap中插入元素或條目,可以使用把(K、V)方法使用。

K密鑰類型

V值的類型

演示put方法的程序:
進口. io . *;進口java.util。*;public class Hashmap {public static void main(String args[]) {Map hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);}}

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

2.刪除元素

刪除(K)方法將鍵作為參數,並刪除映射上存在的給定鍵的條目。我們還有一個刪除(K、V)方法刪除條目。

使用remove()演示刪除操作的程序:
進口. io . *;進口java.util。*;public class Hashmap {public static void main(String args[]) {Map hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);hm.remove(藍色);//刪除藍鍵System.out.println(hm); } }

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

{紅色=1,黃色=4,綠色=3}

刪除(K、V):這個方法接受key和value作為參數,隻有當key和value都匹配時才刪除條目。

使用remove(K, V)刪除條目的程序:

進口. io . *;進口java.util。*;public class Hashmap {public static void main(String args[]) {Map hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);hm.remove(“藍色”,3);System.out.println (hm);; hm.remove("Blue",2); System.out.println(hm); } }

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

{紅色=1,藍色=2,黃色=4,綠色=3}

{紅色=1,黃色=4,綠色=3}

3.訪問元素和遍曆hashmap

3.1使用get(K)訪問與某個鍵關聯的一個特定值

hashmap中的值可以使用該方法訪問得到(K).該鍵必須在參數中傳遞,存儲在該鍵中的值將被獲取。

編寫使用get(K)方法訪問值的程序
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);System.out.println (hm.get(“綠色”);}}

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

3.

3.2隻能訪問元素的鍵

如果您隻想檢索鍵集,鍵盤()方法將隻返回hashmap中的鍵集。

顯示keySet()方法用法的程序
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);System.out.println (hm.keySet ());}}

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

[紅,藍,黃,綠]

3.3隻訪問元素的值

值()方法幫助獲取值集

顯示values()用法的程序:
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);System.out.println (hm.values ());}}

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

[1,2,4,3]

3.4訪問HashMap表項

entrySet ()方法將返回條目集()。

顯示entrySet()用法的程序
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);System.out.println (hm.entrySet ());}}

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

[紅色=1,藍色=2,黃色=4,綠色=3]

3.5遍曆HashMap

在了解了如何訪問hashmap中的元素之後,讓我們看看如何迭代或遍曆hashmap.其思想是使用for-each循環遍曆一組條目,然後使用for-each循環訪問條目中的鍵和值getKey ()而且getValue ()方法。我們使用地圖。條目(K, V) that allows us to access the entries of a map.

編寫遍曆hashmap條目的程序:
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);(地圖。條目 e: hm.entrySet()) { System.out.println(e.getKey()+","+e.getValue()); } } }

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

紅色,1

藍色,2

黃色,4

綠色,3

4.更新值

如果要更新存儲在給定鍵中的值,可以使用把(K、V)

替換()方法。

使用put()更新值的程序
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);hm.put(“黃色”,5);//更新鍵值Yellow System.out.println(hm); } }

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

{紅色=1,藍色=2,黃色=5,綠色=3}

使用replace(K,V)更新程序
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);hm.replace(“黃色”,6);System.out.println (hm); } }

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

{紅色=1,藍色=2,黃色=6,綠色=3}

hashmap的特性

Hashmap是一個基於map的集合類,它包含基於鍵的值。讓我們來討論一下它的一些關鍵特性:

  • 它是一個無序的集合;也就是說,它不會按照插入鍵和值的順序維護鍵和值。
  • 它不能有重複的鍵;但是,它可以有重複的值。
  • 它允許一個空鍵和多個空值。
  • HashMap使用內部類進入< K、V >在多個單鏈表的節點中存儲數據。
  • 其初始默認容量為16,負載係數為0.75
  • 它們不是同步的(不是線程安全的),因為多個線程在訪問時可以修改它們的結構。因此,我們必須從外部同步這些並發的修改。我們可以用collections . synchronizedmap (Hashmap)讓它同步。
  • 它使用了一種叫做哈希將鍵轉換為更短的哈希鍵,從而更容易從哈希映射中插入和檢索數據。我們將在接下來的章節中詳細了解Hashmap的工作原理。

hashmap的內部結構

考慮到hashmap的內部結構,它有一個節點< K、V >哪個代表內部類進入< K、V >用於存儲hashmap的映射。每個鍵值對存儲在Entry類的對象中。該類是Hashmap的靜態內部類。每個節點有四個字段,分別是:

  1. 散列鍵(散列後獲得的較短的鍵)
  2. 關鍵
  3. 價值
  4. 節點next(對另一個條目的引用,就像單鏈表一樣)

了解HashMap中節點的要點:

  • hash屬性存儲鍵的hashcode。
  • Key屬性存儲鍵,它是final類型。
  • 屬性保存元素的值。
  • 條目 next保存指向下一個鍵值對的指針。

內部類Entry的聲明

靜態類Entry實現Map。條目{int哈希;最後的K鍵;V值;條目< K、V >下;}

HashMap中桶的概念

是存儲元素的節點或項的數組。許多節點可以擁有類似的存儲桶。hashmap像單鏈表一樣存儲元素,條目列表被稱為桶。這些節點通過鏈表連接起來。hashmap的容量和桶的個數有如下關係:

HashMap容量=桶數*負載因子

hashmap的結構

HashMap的內部工作

Hashmap使用一種叫做散列。方法將給定鍵轉換為哈希鍵的過程hashCode ()方法。哈希還涉及equals ()方法檢查鍵是否相等。哈希用於更快地索引和檢索項目。hashmap的性能基於hashcode()方法,因此應該仔細選擇該方法。下麵讓我們討論hashCode和equals方法。

1.hashCode ():該方法生成對象的hashcode,並以整數形式返回傳遞的對象的內存引用。它返回每個實例唯一的隨機整數。這種方法的結果稱為a哈希

語法: public int hashCode()

2.equals ():Hashmap使用這個方法來檢查兩個對象是否相等。如果該方法返回true,則它們相等,否則不相等。

語法:boolean =(對象ob)

顯示equals()用法的程序:

進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();HashMap hm1 = new HashMap();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);hm1.put(“紅”,1); hm1.put("Blue",2); hm1.put("Green",3); hm1.put("Yellow",4); System.out.println(hm1); System.out.println(hm.equals(hm1)); } }

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

{紅色=1,藍色=2,黃色=4,綠色=3}

真正的

碰撞

當不同的鍵產生相同的hashcode值,並且元素已經存在於該索引值時,就會發生衝突。為了避免或減少衝突,應該使用一個好的哈希函數,以確保值在整個哈希映射中的最佳分布。當發生衝突時,我們使用鏈接技術,如上麵的第二個例子所示,來分布值。

哈希計算索引

索引是在哈希中生成的,以減少數組的大小。如果將鍵的hashcode用作索引,則獲得的整數值可能很大,可能會增加數組的大小。

該指數的計算公式如下:

索引= hashCode(Key) & (n-1)

N =數組/桶的大小

(默認n = 16)

Put()操作的散列

讓我們考慮一個默認容量為16 (n=16)的空hashmap。

1.沒有碰撞:假設你想新建地圖中的條目(" welcome ",15)。

  • 根據哈希的概念,哈希將首先使用hashCode(鍵)生成。
  • 計算hash = hashCode(" welcome ");[假設是200]
  • 計算索引= hash &(16-1),[計算結果為8]
  • 創建一個帶有散列、鍵、值和引用指針的節點/條目對象。
  • 如果該對象為空,則將其放在索引值8處。

2.碰撞:有時,可能會出現索引相同的情況,並且可能發生碰撞。現在讓我們嚐試在hashmap中插入(" wait ",16)。

  • 計算hash = hashCode(" wait ");[假設是120]
  • 計算索引= hash &(16-1),[計算結果為8]
  • 創建一個帶有散列、鍵、值和引用指針的節點對象。
  • 如果沒有其他值,將該對象放置在索引值8處。
  • 如果有一些值放在那裏,就像在我們的例子中,它是一個碰撞狀態。
  • 萬一發生碰撞,請檢查equals ()如果鍵相似。
  • 如果equals()方法返回true,則將該值替換為當前值。
  • 如果equals()方法返回false,則將這個新節點對象通過具有相同索引值的鏈表指向前一個節點。(鏈接方法)
  • 在本例中,由於鍵、歡迎鍵和等待鍵是不同的,我們將使用鏈接列表放置一個新節點。

Get()操作的散列

讓我們看看如何使用哈希來實現get操作。get(Key)用於獲取給定鍵的值。

例子沒有碰撞

假設您想要找到鍵“welcome”的值,請遵循以下哈希步驟。

  • 計算hash = hashCode(" welcome ");(假設200年)
  • 計算索引=哈希& (n-1), n=16[索引計算結果為8]
  • 檢查索引8;如果此鍵與使用equals()方法的元素的鍵匹配,則返回該值。
  • 如果鍵不匹配,則檢查下一個元素的鍵,依此類推。
  • 在本例中,鍵匹配,因此將返回鍵“welcome”的值,即15。

例子碰撞

假設你想要找到鍵“wait”的值:

  • 計算hash = hashCode(" wait ");(假設120年)
  • 計算索引=哈希& (n-1), n=16[索引計算結果為8]
  • 檢查索引;如果此鍵與使用equals()方法的元素的鍵匹配,則返回該值。
  • 在這裏,它不匹配,所以檢查列表中的下一個元素(下一個節點)。該索引的下一個鍵正在等待。重新檢查鑰匙;它們現在匹配了,所以鍵“wait”[即16]的值將被返回。
  • 如果該節點的下一個引用為空,則返回空,否則移動到下一個節點並重複鍵匹配過程。

hashmap的性能

hashmap的性能基於兩個重要因素:

  1. 初始容量
  2. 負荷係數

初始容量:創建hashmap實例時的初始桶數。默認值為16。也就是說,最初哈希映射可以存儲16個鍵值元素。

負荷係數:它衡量的是在hashmap容量增加之前允許填充多少百分比。默認負載因子值為0.75,通常在0到1之間。

與性能相關的其他術語有:

閾值:它是負載因子和hashmap容量的乘積。默認閾值為0.75*16= 12。當hashmap中填充了12個元素時,我們需要停止向其中插入更多的元素。將進行重哈希,這將使hashmap的容量增加一倍。

再處理:這是一種在達到閾值時將容量翻倍的方法。當超過閾值時,就會重新散列,這樣桶的容量現在是原來的兩倍,操作所需的時間也更短。

HashMap的時間複雜度

說到時間複雜度HashMap的性能操作取決於哈希函數實現.如果哈希代碼實現良好(沒有哈希衝突),則最佳、最差和平均時間複雜度為O (1).在哈希碼實現不好的情況下(哈希會產生衝突),複雜性就會增加O (n).此外,對hashmap的迭代取決於它的容量和鍵-值對。如果容量較大,迭代次數會增加,這會增加時間複雜度,影響性能。

性能改進

關於Hashmap中的性能改進,必須適當選擇兩個因素優化哈希函數而且能力.哈希函數的實現應該是這樣的,即哈希代碼對更少的衝突給予no。保持高容量將增加迭代和時間複雜性,因此必須仔細選擇這兩個因素。

在JAVA 8中所做的更改:

JAVA 8中做了一些哈希映射性能改進,以處理哈希衝突。在Java 8之前,在哈希衝突的情況下,哈希映射的性能很低,這對複雜性有影響。由於衝突,鍵和值都被放在一個節點中,在最壞的情況下,由於鏈表遍曆,複雜度為O(n)。變更如下:

  • 最初,散列映射將把條目存儲在一個鏈表中,但當達到閾值時,將使用自平衡BST樹而不是鏈表。使用BST的好處是我們得到的最壞情況的複雜度是O(log n)。

hashmap中的方法

put(K鍵,V值) 在映射中插入一個條目。
putAll(地圖地圖) 在映射中插入指定的映射。
putIfAbsent(K鍵,V值) 僅在鍵不存在時插入條目。
刪除(K鍵) 刪除指定鍵的條目。
刪除(K鍵,V值) 刪除指定鍵和值的條目。
clear () 從映射中移除所有映射。
isEmpty () 如果映射沒有鍵值映射,則返回true。
尺寸() 返回鍵值映射的個數。
鍵盤() 在hashmap中返回一組鍵。
值() 在hashmap中返回一組值。
entrySet () 在hashmap中返回一組條目(K, V)。
得到(K鍵) 返回與給定鍵相關聯的值。
替換(K鍵,V值) 將指定的鍵替換為指定的值。
替換(K鍵,V舊值,V新值) 將指定鍵的舊值替換為新值。
containsKey (K鍵) 如果指定的鍵存在於hashmap中,則返回true。
containsValue (V值) 如果指定的值存在於hashmap中,則返回true。
hashCode () 以整數形式返回對象的內存地址
=(對象O) 將指定對象與映射進行比較,如果相同則返回true。
克隆() 返回hashmap實例的淺拷貝。
getOrDefault(K鍵,V默認值) 返回給定鍵映射到的值,如果鍵未映射則返回默認值。
空白forEach (BiConsumer < ?超級K, ?超級V>動作) 它將對所有條目執行給定的操作,直到它們全部被處理或拋出異常。
V merge(K鍵,V值,biffunction 的remappingFunction 如果指定的鍵未映射到任何值,或者鍵為空,則將其映射為給定值。
空白replaceAll (BiFunction < ?超級K, ?超級V, ?擴展V>函數) 它將在處理後用函數的結果替換每個條目值。
V計算(K鍵,biffunction 的remappingFunction 計算指定鍵及其當前映射值的映射。如果當前沒有映射,則返回null。
V computeIfAbsent(K鍵,函數的映射函數 如果指定的鍵還沒有與某個值相關聯(或映射為null),則使用給定的映射函數計算值,並將其輸入到此映射中,除非為null。
V computeIfPresent(K鍵,biffunction 的remappingFunction 給定鍵及其當前映射值(如果指定鍵的值存在且非空),計算一個新的映射。

上麵定義的hashmap的其他基本函數的一些例子:

程序顯示hashmap的大小:
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);System.out.println (hm.size ());}}

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

4

編程顯示putAll()和putIfAbsent()方法
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);HashMap hm1 = new HashMap();hm1.putAll (hm); //putAll System.out.println(hm1); hm.putIfAbsent("Orange",7); //putIfAbsent System.out.println(hm); } }

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

{紅色=1,藍色=2,黃色=4,綠色=3}

{紅色=1,藍色=2,黃色=4,橙色=7,綠色=3}

編程來顯示containsKey()和containsValue()方法
進口. io . *;進口java.util。*;public class Hashmap{public static void main(String args[]) {Hashmap  hm = new Hashmap ();hm.put(“紅”,1);hm.put("藍色",2);hm.put(“綠色”,3);hm.put(“黃色”,4);System.out.println (hm);System.out.println (hm.containsKey(“綠色”);System.out.println (hm.containsKey(“橙色”)); System.out.println(hm.containsValue(3)); System.out.println(hm.containsValue(7)); } }

輸出

{紅色=1,藍色=2,黃色=4,綠色=3}

真正的

真正的

同步的HashMap

如上所述,hashmap是非同步的,這意味著它們不是線程安全的。當同時訪問hashmap時,多個線程可以從結構上改變它,然後必須從外部同步。外部同步可以通過以下方式完成:

映射m =集合。synchronizedMap (Hashmap地圖);

想知道去哪裏學習夢寐以求的課程免費索取技能?看看關於beplay2018官网卓越學習學院

《阿凡達》的照片
beplay2018官网優秀的學習團隊
beplay2018官网Great Learning的博客涵蓋了最新的技術發展和創新,可以用來建立有價值的職業生涯。你會找到職業指南、技術教程和行業新聞,讓自己跟上快速變化的技術和商業世界。

留下評論

你的電郵地址將不會公布。必填字段已標記

與夢想的工作免費的印度最值得信賴的教育平台上的證書課程

滾動到頂部
Baidu
map