JavaRush /Java Blog /Random-TW /HashMap 和 ConcurrentHashMap 熱門面試問題
furs08
等級 11

HashMap 和 ConcurrentHashMap 熱門面試問題

在 Random-TW 群組發布
在我的上一篇預覽中,我談到了「HashMap 在 Java 中如何運作」。我討論了這個類別的內部結構以及它們如何融入這個概念。但當我被問到HashMap以及相關的東西時,提問者並不是只停留在基本概念上。在討論的過程中,涉及到不同的方向,最終都取決於你是否真正了解這些東西。 HashMap 和 ConcurrentHashMap 熱門面試題 - 1在本預覽中,我將嘗試涵蓋面試問題的所有主要主題: 涵蓋的主題:
  1. 如何為 HashMap 創建鍵?
  2. HashMap 和 ConcurrentHashMap 的差別?
  3. Collections.synchronizedMap(HashMap) 與 HashMap 的差異?
  4. ConcurrentHashMap 和 Collections.synchronizedMap(HashMap) 的差異?
  5. HashMap 和 HashTable 的差別?
  6. HashTable 和 Collections.synchronizedMap(HashMap) 的差異?
  7. 隨機/固定 hashCode() 值對鍵的影響
  8. 在多執行緒應用程式中的非同步程式碼中使用 HashMap
讓我們開始吧:
  1. 為 HashMap 產生鍵

    主要需求之一是我們必須無錯誤地傳回物件的值。正確的?否則,不清楚如何想像你正在設計的資料結構。將無法使用。為了確定我們已經創建了一個好的金鑰,我們需要知道 HashMap 是如何運作的。HashMap 是建立在哈希原理之上的。哈希碼中的鍵主要與 equals() 方法結合使用,以在 HashMap 中新增和搜尋元素。如果將一個物件的雜湊碼改為另一個鍵值對,那麼從Map中取得值幾乎是不可能的。這種情況稱為記憶體洩漏。為了避免這種情況,鍵和映射必須是不可變的。這就是為什麼 String、Integer 等不可變類別和其他類似類別是建立鍵的好選擇的主要原因。

    但請記住,建議使用不變性,但不是必要的。如果你想讓一個可變物件成為鍵,那麼你必須確保鍵物件不會改變該物件的哈希碼。這可以透過重寫 hashCode() 方法來完成。此外,關鍵類別必須與 hashCode() 和 equals() 方法正確配合,以避免不必要的和令人驚訝的執行行為。

  2. HashMap 和 ConcurrentHashMap 的區別

    Whatбы лучше визуализировать СoncurrentHashMap нужно рассматривать этот класс How группу HashMap’ов. Whatбы брать и класть значения пар(key-value) в HashMap необходимо вычислить хэш-code и найти правильный сегмент массива Collection.Entry. В ConcurrentHashMap отличие заключается во внутренней структуре для хранения пар key-value. ConcurrentHashMap имеет дополнительную концепцию сегментов. Будет легко понять если представить, что один сегмент эквивалентен одному HashMap[концептуально]. ConcurrentHashMap разделена на множество сегментов [по умолчанию их число равно 16] при инициализации. ConcurrentHashMap похожим потокам примерно (16) получать одновременный доступ к этому сегменту, каждый поток работает одновременно с высоким параллелизмом. Отсюда, если ваша пара key-value хранится в сегменте 10 не нужно блокировать остальные 15 сегментов дополнительно. Такая структура обеспечивает очень высокий уровень параллелизма.

    HashMap 和 ConcurrentHashMap 熱門面試問題 - 2

    Другими словами Concurrent HashMap использует множество замков и каждый замок управляет одним сегментом структуры. Установки данных в определенном сегменте заблокированы для получения в этом сегменте так синхронизированы операции обновления. При получении данных, чтения на лету используется без синхронизации. Если считывать данные на лету то сегмент блокируется и запись производится в синхронизированный блок.

  3. Различия между HashMap и Collection.synchronizedMap(HashMap)

    Все на самом деле просто! HashMap не синхронизирована и Collection.synchronizedMap(HashMap) возвращает упакованные методы HashMap которые являются синхронизированными get и put методами.

    Фактически, Collection.synchronizedMap(HashMap) внутренне созданного внутреннего класса SunchronizedMap содержащего пары key-value передающиеся в HashMap How аргумент. Такой пример внутренних классов ничего не меняет в первоначальных параметрах HashMap и является fully независимым.

  4. Различия между ConcurrentHashMap и Collections.synchronizedMap(HashMap)

    Оба являются синхронизированными versionми HashMap c различиями в функциональности и внутренней структуре. Как указано выше ConcurrentHashMap состоит из внутренних сегментов, которые могут рассматриваться How независимые HashMap’ы концептуально. Все эти сегменты могу быть заблокированы отдельными потоками выполняемыми одновременно. Таким образом несколько потоков могу одновременно получить/положить пары key-value из ConcurrentHashMap без блокирования/ожидания друг друга.

    Из Collections.synchronizedMap() мы получаем синхронизированную версию HashMap и доступ в блокировании образом. Это означает то что если несколько потоков пытаются получить доступ к synchronizedMap в одно и тоже время им будет позволено взять/положить пары key-value по одному синхронизированному образу.

  5. Различия между HashMap и HashTable

    Этот вопрос также является простым. Главное различие в том что HashTable синхронизирован а HashMap нет. Если вас спросят по другим причинам то скажите им что HashTable является наследием класса (часть JDK 1.0) который был произведен в рамках коллекции реализовав интерфейс Map позже. В нем все еще есть вещи которых нету в HashMap такие к примеру How Enumerators(счётчики). Другой незначительной причиной является то что HashMap поддерживает ключ со meaningм null.(Отображаемый How пустая область памяти). HashTable не поддерживает ключ со meaningм null и вызывает исключение NullPointerException, при попытке его задать.

  6. Различия между HashTable и Collection.synchronized(HashMap)

    До сих пор вы возможно только знали об их сходствах. Оба являются синхронизированными versionми коллекций. Оба имеют синхронизированные методы внутри. Оба блокируют потоки и заставляют ждать когда можно взять/положить что-либо в коллекцию. Так в чем же различия? Хорошо! Нет основных различий для указанных выше причин. Производительность обоих одинакова. Единственное что различает их это то что HashTable наследуемый класс он получил свои дополнительные функции такие How Enumerators(счетчики).

  7. Влияние случайных/фиксированных значений для значения ключа.

    Влияние в обоих случаях будь то фиксированное meaning or случайное будет иметь одинаковый результат и это необъяснимое поведение. Большое meaning имеет место в HashMap где поставить пару key-value и где восстановить. Если положение an object ключа меняется каждый раз то его положение будет рассчитываться каждый раз разными способами. Таким образом an object хранящийся в HashMap будет потерян навсегда с минимальной возможностью восстановления. Поэтому значения ключей являются неизменными и каждый раз возвращают уникальные значения.

  8. Использование HashMap в несинхронизированном codeе многопоточных приложений.

    — в худшем случае это может вызвать бесконечный цикл.

    — Да.

    — Ты был прав это действительно может привести к бесконечному циклу. Ты спросишь: "Как?"

    — Хорошо! Вот причина!

    HashMap имеет концепцию повторного хеширования, когда достигает своего верхнего предела. Это процесс создания новой области памяти и копирования туда существующих элементов. Допустим Поток A положил пару key-value в Map и повторное хеширование началось, в то же время поток Б начал манипулировать с областью памяти используя операцию put(положить). Во время повторного хеширования существует возможность для создания циклической зависимости где элемент находящийся в ссылочном листе [в любой области памяти] может указывать на любой предыдущий узел в ту же область памяти. Это приведет к бесконечному циклу так How code повторного хеширования содержит в себе while(TRUE) {//получаем следующий узел} который будет работать бесконечно.

    Посмотрите внимательно на этот code содержащий метод передачи использующий операцию повторного хеширования:

    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;
        }
    }

    下一篇文章將詳細介紹這一點。如果您覺得文章有用,請分享給您的朋友!快樂學習!

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION