欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的HashMap集合深度解析

 更新時間:2023年09月14日 11:27:30   作者:尋道的 Programmer  
這篇文章主要介紹了Java中的HashMap集合深度解析, HashMap可以說是Java中最常用的集合類框架之一,是Java語言中非常典型的數(shù)據(jù)結(jié)構(gòu),我們總會在不經(jīng)意間用到它,很大程度上方便了我們?nèi)粘i_發(fā),需要的朋友可以參考下

HashMap

HashMap可以說是Java中最常用的集合類框架之一,是Java語言中非常典型的數(shù)據(jù)結(jié)構(gòu),我們總會在不經(jīng)意間用到它,很大程度上方便了我們?nèi)粘i_發(fā)。

在很多Java的筆試題中也會被問到,最常見的,“HashMap和HashTable有什么區(qū)別?”,這也不是三言兩語能說清楚的,這種筆試題就是考察你來筆試之前有沒有復習功課,隨便來個快餐式的復習就能給出簡單的答案。

言歸正傳,了解HashMap之前,我們需要知道Object類的兩個方法hashCode和equals,我們先來看一下這兩個方法的默認實現(xiàn):

/** JNI,調(diào)用底層其它語言實現(xiàn) */
public native int hashCode();
/** 默認同==,直接比較對象 */
public boolean equals(Object obj) {
	return (this == obj);
}

equals方法我們太熟悉了,我們經(jīng)常用于字符串比較,String類中重寫了equals方法,比較的是字符串值,看一下源碼實現(xiàn):

public boolean equals(Object anObject) {
	if (this == anObject) {
		return true;
	}
	if (anObject instanceof String) {
		String anotherString = (String) anObject;
		int n = value.length;
		if (n == anotherString.value.length) {
			char v1[] = value;
			char v2[] = anotherString.value;
			int i = 0;
			// 逐個判斷字符是否相等
			while (n-- != 0) {
				if (v1[i] != v2[i])
						return false;
				i++;
			}
			return true;
		}
	}
	return false;
}

重寫equals要滿足幾個條件:

  • 自反性:對于任何非空引用值 x,x.equals(x) 都應返回 true。
  • 對稱性:對于任何非空引用值 x 和 y,當且僅當 y.equals(x) 返回 true 時,x.equals(y) 才應返回 true。
  • 傳遞性:對于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 應返回 true。
  • 一致性:對于任何非空引用值 x 和 y,多次調(diào)用 x.equals(y) 始終返回 true 或始終返回 false,前提是對象上 equals 比較中所用的信息沒有被修改。
  • 對于任何非空引用值 x,x.equals(null) 都應返回 false。

Object 類的 equals 方法實現(xiàn)對象上差別可能性最大的相等關系;即,對于任何非空引用值 x 和 y,當且僅當 x 和 y 引用同一個對象時,此方法才返回 true(x == y 具有值 true)。當此方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的常規(guī)協(xié)定,該協(xié)定聲明相等對象必須具有相等的哈希碼。

下面來說說hashCode方法,這個方法我們平時通常是用不到的,它是為哈希家族的集合類框架(HashMap、HashSet、HashTable)提供服務,hashCode 的常規(guī)協(xié)定是:

  • 在 Java 應用程序執(zhí)行期間,在同一對象上多次調(diào)用 hashCode 方法時,必須一致地返回相同的整數(shù),前提是對象上 equals 比較中所用的信息沒有被修改。從某一應用程序的一次執(zhí)行到同一應用程序的另一次執(zhí)行,該整數(shù)無需保持一致。 
  • 如果根據(jù) equals(Object) 方法,兩個對象是相等的,那么在兩個對象中的每個對象上調(diào)用 hashCode 方法都必須生成相同的整數(shù)結(jié)果。 
  • 以下情況不 是必需的:如果根據(jù) equals(java.lang.Object) 方法,兩個對象不相等,那么在兩個對象中的任一對象上調(diào)用 hashCode 方法必定會生成不同的整數(shù)結(jié)果。但是,程序員應該知道,為不相等的對象生成不同整數(shù)結(jié)果可以提高哈希表的性能。

當我們看到實現(xiàn)這兩個方法有這么多要求時,立刻凌亂了,幸好有IDE來幫助我們,Eclipse中可以通過快捷鍵alt+shift+s調(diào)出快捷菜單,選擇Generate hashCode() and equals(),根據(jù)業(yè)務需求,勾選需要生成的屬性,確定之后,這兩個方法就生成好了,我們通常需要在JavaBean對象中重寫這兩個方法。

好了,這兩個方法介紹完之后,我們回到HashMap。HashMap是最常用的集合類框架之一,它實現(xiàn)了Map接口,所以存儲的元素也是鍵值對映射的結(jié)構(gòu),并允許使用null值和null鍵,其內(nèi)元素是無序的,如果要保證有序,可以使用LinkedHashMap。HashMap是線程不安全的,下篇文章會討論。

HashMap的類關系如下:

java.util Class HashMap<K,V>

java.lang.Object
  |--java.util.AbstractMap<K,V>
      |--java.util.HashMap<K,V>

所有已實現(xiàn)的接口:

Serializable,Cloneable,Map<K,V>

直接已知子類:

LinkedHashMap,PrinterStateReasons

HashMap中我們最長用的就是put(K, V)和get(K)。我們都知道,HashMap的K值是唯一的,那如何保證唯一性呢?我們首先想到的是用equals比較,沒錯,這樣可以實現(xiàn),但隨著內(nèi)部元素的增多,put和get的效率將越來越低,這里的時間復雜度是O(n),假如有1000個元素,put時最差情況需要比較1000次。

實際上,HashMap很少會用到equals方法,因為其內(nèi)通過一個哈希表管理所有元素,哈希是通過hash單詞音譯過來的,也可以稱為散列表,哈希算法可以快速的存取元素,當我們調(diào)用put存值時,HashMap首先會調(diào)用K的hashCode方法,獲取哈希碼,通過哈希碼快速找到某個存放位置,這個位置可以被稱之為 bucketIndex,但可能會存在多個元素找到了相同的 bucketIndex,有個專業(yè)名詞叫 碰撞,當碰撞發(fā)生時,這時會取到 bucketIndex位置已存儲的元素,最終通過equals來比較,equals方法就是碰撞時才會執(zhí)行的方法,所以前面說HashMap很少會用到equals。

HashMap通過hashCode和equals最終判斷出K是否已存在,如果已存在,則使用新V值替換舊V值,并返回舊V值,如果不存在 ,則存放新的鍵值對<K, V>到 bucketIndex位置。文字描述有些亂,通過下面的流程圖來梳理一下整個put過程。

現(xiàn)在我們知道,執(zhí)行put方法后,最終HashMap的存儲結(jié)構(gòu)會有這三種情況,我們當然期望情形3是最少發(fā)生的(效率最低)。到目前為止,我們了解了兩件事:

  • HashMap通過鍵的hashCode來快速的存取元素。
  • 當不同的對象發(fā)生碰撞時,HashMap通過單鏈表來解決,將新元素加入鏈表表頭,通過next指向原有的元素。單鏈表在Java中的實現(xiàn)就是對象的引用(復合)。

來鑒賞一下HashMap中put方法源碼:

public V put(K key, V value) {
	// 處理key為null,HashMap允許key和value為null
	if (key == null)
		return putForNullKey(value);
	// 得到key的哈希碼
	int hash = hash(key);
	// 通過哈希碼計算出bucketIndex
	int i = indexFor(hash, table.length);
	// 取出bucketIndex位置上的元素,并循環(huán)單鏈表,判斷key是否已存在
	for (Entry<K,V> e = table[i]; e != null; e = e.next) {
		Object k;
		// 哈希碼相同并且對象相同時
		if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
			// 新值替換舊值,并返回舊值
			V oldValue = e.value;
			e.value = value;
			e.recordAccess(this);
			return oldValue;
		}
	}
	// key不存在時,加入新元素
	modCount++;
	addEntry(hash, key, value, i);
	return null;
}

到這里,我們了解了HashMap工作原理的一部分,那還有另一部分,如,加載因子及rehash,HashMap通常的使用規(guī)則,多線程并發(fā)時HashMap存在的問題等等,這些會留在下一章說明。

到此這篇關于Java中的HashMap集合深度解析的文章就介紹到這了,更多相關Java中的HashMap內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 解決SpringMvc后臺接收json數(shù)據(jù)中文亂碼問題的幾種方法

    解決SpringMvc后臺接收json數(shù)據(jù)中文亂碼問題的幾種方法

    本篇文章主要介紹了解決SpringMvc后臺接收json數(shù)據(jù)中文亂碼問題的幾種方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 詳解java google Thumbnails 圖片處理

    詳解java google Thumbnails 圖片處理

    這篇文章主要介紹了java google Thumbnails 圖片處理的相關知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • 在netty中使用native傳輸協(xié)議的方法

    在netty中使用native傳輸協(xié)議的方法

    這篇文章主要介紹了在netty中使用native傳輸協(xié)議,這里我們只以Kqueue為例介紹了netty中native傳輸協(xié)議的使用,需要的朋友可以參考下
    2022-05-05
  • Java面試必備之ArrayList陷阱解析

    Java面試必備之ArrayList陷阱解析

    昨天小楓接到了一個公司的面試電話,其中一道面試題覺得有點意思,在這里和大家一起分享下。面試題是ArrayList如何刪除指定元素。乍聽很簡單的問題,但是如果沒有實際踩過坑很容易掉進面試官的陷阱中,我們一起來分析下吧
    2022-02-02
  • Java NIO實例UDP發(fā)送接收數(shù)據(jù)代碼分享

    Java NIO實例UDP發(fā)送接收數(shù)據(jù)代碼分享

    這篇文章主要介紹了Java NIO實例UDP發(fā)送接收數(shù)據(jù)代碼分享,分享了客戶端和服務端完整代碼,小編覺得還是挺不錯的,共需要的朋友參考。
    2017-11-11
  • SpringBoot3集成swagger文檔的使用方法

    SpringBoot3集成swagger文檔的使用方法

    本文介紹了Swagger的誕生背景、主要功能以及如何在Spring Boot 3中集成Swagger文檔,Swagger可以幫助自動生成API文檔,實現(xiàn)與代碼同步,并提供交互式測試功能,使用方法包括導入依賴、配置文檔、使用常見注解以及訪問生成的Swagger UI和文檔,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • 解決springboot 連接 mysql 時報錯 using password: NO的方案

    解決springboot 連接 mysql 時報錯 using password: NO的方案

    在本篇文章里小編給大家整理了關于解決springboot 連接 mysql 時報錯 using password: NO的方案,有需要的朋友們可以學習下。
    2020-01-01
  • Java web.xml之contextConfigLocation作用案例詳解

    Java web.xml之contextConfigLocation作用案例詳解

    這篇文章主要介紹了Java web.xml之contextConfigLocation作用案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • SpringBoot指標監(jiān)控功能實現(xiàn)

    SpringBoot指標監(jiān)控功能實現(xiàn)

    這篇文章主要介紹了SpringBoot指標監(jiān)控功能實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • Java中處理郵件附件的方法(本地文件和在線URL)

    Java中處理郵件附件的方法(本地文件和在線URL)

    這篇文章主要介紹了在Java中處理郵件附件的方法,針對本地文件和在線URL兩種附件來源,提供了兩種解決方案,并提供了下載文件和發(fā)送郵件的代碼示例,需要的朋友可以參考下
    2025-03-03

最新評論