<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # `HashMap`和`ConcurrentHashMap`面試問題 > 原文: [https://howtodoinjava.com/interview-questions/hashmap-concurrenthashmap-interview-questions/](https://howtodoinjava.com/interview-questions/hashmap-concurrenthashmap-interview-questions/) 關于“[**`HashMap`如何在 Java 中工作**](//howtodoinjava.com/java/collections/how-hashmap-works-in-java/ "How hashmap works in java")”,我解釋了`HashMap`或`ConcurrentHashMap`類的內部結構以及它們如何適合整個概念。 但是,當面試官向您詢問有關`HashMap`相關概念時,他不僅會停留在核心概念上。 討論通常會朝多個方向進行,以了解您是否真正了解該概念。 在這篇文章中,我將嘗試在`HashMap`和 `ConcurrentHashMap`上涵蓋一些相關的[**面試問題**](//howtodoinjava.com/java-interview-questions/ "interview questions")。 ## `HashMap`和`ConcurrentHashMap`面試問題 1. [您將如何為`HashMap`設計一個好的鍵?](#1) 2. [`HashMap`和`ConcurrentHashMap`之間的區別?](#2) 3. [`HashMap`和`Collections.synchronizedMap(HashMap)`之間的區別嗎?](#3) 4. [`ConcurrentHashMap`和`Collections.synchronizedMap(HashMap)`之間的區別?](#4) 5. [`HashMap`和`HashTable`之間的區別?](#5) 6. [`HashTable`和`Collections.synchronized(HashMap)`之間的區別?](#6) 7. [鍵的隨機/固定`hashCode()`值的影響?](#7) 8. [在多線程應用的非同步代碼中使用`HashMap`嗎?](#8) ## 1.如何為`HashMap`設計一個好的鍵 設計一個好的鍵的最基本的需求是“我們應該能夠從映射中檢索到值對象而不會失敗”,對嗎? 否則,無論您如何構建精美的數據結構,它都將毫無用處。 要確定我們已經創建了一個好的鍵,我們必須知道“[**`HashMap`如何工作?**](https://howtodoinjava.com/java/collections/how-hashmap-works-in-java/ "How hashmap works in java")。 我將介紹哈希表的工作原理,讓您從鏈接的文章中閱讀內容,但總而言之,它是基于哈希原理的。 鍵的哈希碼主要與`equals()`方法結合使用,用于將鍵放入映射,然后從映射中搜索回來。 因此,如果在將鍵值對放入映射后,鍵對象的哈希碼發生變化,則幾乎不可能從映射取回值對象。 這是內存泄漏的情況。 為了避免這種情況,映射**鍵應該是不可變的**。 這些是[**創建類**](https://howtodoinjava.com/java/basics/how-to-make-a-java-class-immutable/ "How to make a java class immutable")不變的東西。 這就是為什么不可變類(例如`String`,`Integer`或其他包裝器類)是好的關鍵對象候選對象的主要原因。 但是請記住,建議**不可變,而不是強制性**。 如果要將可變對象作為`HashMap`中的鍵,則必須確保鍵對象的**狀態更改不會更改對象**的哈希碼。 這可以通過覆蓋`hashCode()`方法來完成。 同樣,鍵類必須遵守[**`hashCode()`和`equals()`方法協定**](https://howtodoinjava.com/java/basics/java-hashcode-equals-methods/ "Working with hashCode and equals methods in java"),以避免在運行時出現不良行為。 在鏈接的文章中閱讀有關此約定的更多信息。 更詳細的信息可在[**在此處**](https://howtodoinjava.com/java/collections/design-good-key-for-hashmap/ "How to design a good key for HashMap")找到。 ## 2\. `HashMap`和`ConcurrentHashMap`之間的區別 為了更好地可視化`ConcurrentHashMap`,請將其視為一組`HashMap`。 要從`HashMap`中獲取和放置鍵值對,您必須計算哈希碼并在`Collection.Entry`數組中查找正確的存儲桶位置。 其余的,您已閱讀了以前有關哈希表如何工作的相關文章。 在`currentHashMap`中,**的不同之處在于內部結構來存儲這些鍵值對**。 `ConcurrentHashMap`具有段的附加概念。 當您想到一個段等于一個`HashMap`時,概念上會更容易理解。 初始化時,并發`HashMap`的段數默認為 16。 `ConcurrentHashMap`允許相似數量(16)的線程同時訪問這些段,以便在高并發期間每個線程都在特定的段上工作。 這樣,如果您的鍵值對存儲在第 10 段中; 代碼不需要另外阻塞其他 15 個段。 這種結構提供了很高的并發性。 ![ConcurrentHashMap Internal Structure](https://img.kancloud.cn/1e/fc/1efc05472707ac5b47da82a4f4c35418_500x255.png) `ConcurrentHashMap`內部結構 換句話說,`ConcurrentHashMap`使用多個鎖,每個鎖控制映射的一個段。 在特定段中設置數據時,將獲得該段的鎖。 因此,基本上**更新操作是同步的**。 **獲取數據時,將使用易失性讀取**,而不會進行任何同步。 如果易失性讀取導致未命中,則將獲得該段的鎖定,并在同步塊中再次搜索項目。 ## 3\. `HashMap`和`Collections.synchronizedMap(HashMap)`之間的區別 這個問題很簡單,對! `HashMap`是不同步的,并且`Collections.synchronizedMap()`返回`HashMap`的包裝實例,該實例具有同步的所有`get`,`put`方法。 本質上,`Collections.synchronizedMap()`返回內部創建的內部類“`SynchronizedMap`”的引用,該類包含作為參數傳遞的輸入`HashMap`的鍵值對。 內部類的此實例與原始參數`HashMap`實例無關,并且是完全獨立的。 ## 4\. `ConcurrentHashMap`和`Collections.synchronizedMap(HashMap)`之間的區別 這一點要難一些。 兩者都是`HashMap`的同步版本,其核心功能和內部結構有所不同。 如上所述,`ConcurrentHashMap`由內部段組成,從概念上講,這些內部段可以視為獨立的`HashMap`。 所有這樣的段可以在高并發執行中被單獨的線程鎖定。 這樣,**多個線程可以從`ConcurrentHashMap`獲取/放置鍵值對,而不會互相阻塞/等待**。 在`Collections.synchronizedMap()`中,我們獲得了`HashMap`的同步版本,并且**以阻塞方式**進行訪問。 這意味著如果多個線程嘗試同時訪問`synchronizedMap`,將允許它們一次以同步方式獲取/放置鍵值對。 ## 5\. `HashMap`和`HashTable`之間的區別 這也是一個很簡單的問題。 主要區別在于`HashTable`是同步的,而`HashMap`不是。 如果由于其他原因而被告知,請告訴他們,`HashTable`是舊類(JDK 1.0 的一部分),該類稍后通過實現`Map`接口而被提升為集合框架。 它仍然具有一些**附加功能,例如`HashMap`缺少的`Enumerator`**。 另一個較小的原因可能是:`HashMap`支持空鍵(映射到零桶),`HashTable`不支持空鍵,并且在這種嘗試時拋出`NullPointerException`。 ## 6\. `HashTable`和`Collections.synchronized(HashMap)`之間的區別 到目前為止,您必須已經了解了它們之間相似性的核心思想。 兩者都是集合的同步版本。 兩者都在類內部具有同步方法。 兩者本質上都是阻塞的,即在將實例中的任何內容放進去之前,多個線程將需要等待獲取實例上的鎖。 那么區別是什么呢。 好吧,由于上述原因,**沒有重大差異**。 兩個集合的性能也相同。 唯一將它們分開的是事實,`HashTable`是提升為集合框架的舊版類。 它具有自己的額外功能,例如枚舉器。 ## 7.鍵的隨機/固定`hashcode()`值的影響 兩種情況(鍵的固定哈希碼或鍵的隨機哈希碼)的影響將產生相同的結果,即“**意外行為**”。 `HashMap`中哈希碼最基本的需求是確定存儲桶的位置,以將鍵值對放置在哪里,以及必須從哪里檢索它。 如果鍵對象的哈希碼每次都更改,則鍵值對的確切位置每次都將計算為不同。 這樣,存儲在`HashMap`中的一個對象將永遠丟失,并且將其從映射取回的可能性極小。 出于同樣的原因,建議鍵是不可變的,以便每次在同一鍵對象上請求時,它們都返回唯一且相同的哈希碼。 ## 8.在多線程應用中的非同步代碼中使用`HashMap` 在正常情況下,它**可使`HashMap`處于不一致狀態**,在該狀態下添加和檢索的鍵值對可能不同。 除此之外,還會出現其他令人驚訝的行為,例如`NullPointerException`。 在最壞的情況下,**會導致無限循環**。 是。 你答對了。 它可能導致無限循環。 你問什么,如何? 好吧,這就是原因。 當`HashMap`達到其大小上限時,它具有重新哈希的概念。 重新哈希處理是創建新的內存區域,并在新的內存中復制所有已經存在的鍵值對的過程。 可以說,線程 A 嘗試將鍵值對放入映射中,然后開始重新哈希。 同時,線程 B 來了,并開始使用`put`操作來操作存儲桶。 在進行重新哈希處理時,有機會生成循環依賴關系,其中鏈表中的任何元素(在任何存儲桶中)都可以指向同一存儲桶中的任何先前節點。 這將導致無限循環,因為重新哈希處理的代碼包含一個“`while(true){//獲取下一個節點;}`”塊,并且在循環依賴項下它將無限運行。 要仔細觀察,請查看用于重新哈希處理的傳輸方法的藝術源代碼: ```java public Object get(Object key) { Object k = maskNull(key); int hash = hash(k); int i = indexFor(hash, table.length); Entry e = table[i]; //While true is always a bad practice and cause infinite loops while (true) { if (e == null) return e; if (e.hash == hash & eq(k, e.key)) return e.value; e = e.next; } } ``` 以后我會寫一篇更詳細的文章。 希望我能夠為`HashMap`面試問題和`ConcurrentHashMap`面試問題投入更多知識。 如果您認為本文有幫助,請考慮與您的朋友分享。 學習愉快! 參考文獻: [`ConcurrentHashMap` Java 文檔](https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/ConcurrentHashMap.html) [`HashMap` Java 文檔](https://docs.oracle.com/javase/10/docs/api/java/util/HashMap.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看