JavaRush /Java 博客 /Random-ZH /HashMap 和 ConcurrentHashMap 热门面试问题
furs08
第 11 级

HashMap 和 ConcurrentHashMap 热门面试问题

已在 Random-ZH 群组中发布
在我的上一篇预览中,我谈到了“ 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