Яка користь від додавання нульового ключа або значення до HashMap в Java?


91

HashMap допускає один нульовий ключ і будь-яку кількість нульових значень. Яка користь від цього?


11
"Можливо, проблема не в тому, що нас ніщо не турбує, а в тому, що ми турбуємо це".
bmargulies

3
У колекціях Google у колекціях Google у багатьох класах не допускається значення null, і аргументи за цим полягають у тому, що 95% випадків не потребують значення null, і вони можуть представляти помилки, які потенційно важко знайти.
stivlo

Дивна річ у тому, що ConcurrentHashMapвона не підтримує нульові клавіші, тоді як HashMapпідтримує.
codepleb

2
Тільки HashMap дозволяє нуль :)
subhashis

Відповіді:


126

Я не впевнений у тому, що ви запитуєте, але якщо ви шукаєте приклад того, коли хотіли б використовувати нульовий ключ, я часто використовую їх на картах для представлення регістру за замовчуванням (тобто значення, яке слід використовувати якщо заданий ключ відсутній):

Map<A, B> foo;
A search;
B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);

HashMapспеціально обробляє нульові ключі (оскільки він не може викликати .hashCode()нульовий об'єкт), але нульові значення не є чимось особливим, вони зберігаються на карті як будь-що інше


4
Отже, якщо .hashCode () неможливий для null, хто вирішує, в який каретку буде вводитися нульовий ключ?
Pacerier

26
@Pacerier Існує спеціальний метод у HashMap( putForNullKey), який обробляє його; він зберігає це в таблиці 0
Michael Mrozek

1
@MichaelMrozek ваш останній рядок, B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);я думаю, ми можемо просто викликати метод get за ключем пошуку, який матиме той самий результат. B val = foo.get(search);не могли б ви виправити мене, якщо я щось помиляюся?
dheerajraaj

6
@ Dheeraj92 Ваш код буде встановлено valв nullразі , якщо ключ не існує; mine встановлює його на будь-які nullкарти на карті. У цьому була суть, я зберігаю ненульове значення за замовчуванням у nullключі на карті і використовую його, якщо фактичний ключ не існує
Michael Mrozek

28

Одним з прикладів може бути моделювання дерев. Якщо ви використовуєте HashMap для представлення деревної структури, де ключ є батьківським, а значення - списком дочірніх, тоді значеннями nullключа будуть кореневі вузли.


6

Одним із прикладів використання null значень є використання HashMapкеша як результату дорогої операції (наприклад, виклику зовнішньої веб-служби), яка може повернутися null.

nullПотім введення значення на карту дозволяє розрізнити випадок, коли операція не була виконана для даного ключа ( cache.containsKey(someKey)повертається false), і де операція була виконана, але повернуло nullзначення ( cache.containsKey(someKey)повертає true, cache.get(someKey)повертає null).

Без nullзначень вам доведеться або ввести якесь спеціальне значення в кеш, щоб вказати nullвідповідь, або просто взагалі не кешувати цю відповідь і виконувати операцію кожного разу.


3

Поки що відповіді лише вважають, що варто мати nullключ, але питання також задає питання any number of null values.

Перевага зберігання значення nullпроти ключа в HashMap така ж, як і в базах даних тощо - ви можете записати різницю між значенням, яке є порожнім (наприклад, рядок ""), і відсутністю значення взагалі (null) .


2

Ось мій єдиний надуманий приклад випадку, коли nullключ може бути корисним:

public class Timer {
    private static final Logger LOG = Logger.getLogger(Timer.class);
    private static final Map<String, Long> START_TIMES = new HashMap<String, Long>();

    public static synchronized void start() {
        long now = System.currentTimeMillis();
        if (START_TIMES.containsKey(null)) {
            LOG.warn("Anonymous timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(null).longValue()) +"ms"); 
        }
        START_TIMES.put(null, now);
    }

    public static synchronized long stop() {
        if (! START_TIMES.containsKey(null)) {
            return 0;
        }

        return printTimer("Anonymous", START_TIMES.remove(null), System.currentTimeMillis());
    }

    public static synchronized void start(String name) {
        long now = System.currentTimeMillis();
        if (START_TIMES.containsKey(name)) {
            LOG.warn(name + " timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(name).longValue()) +"ms"); 
        }
        START_TIMES.put(name, now);
    }

    public static synchronized long stop(String name) {
        if (! START_TIMES.containsKey(name)) {
            return 0;
        }

        return printTimer(name, START_TIMES.remove(name), System.currentTimeMillis());
    }

    private static long printTimer(String name, long start, long end) {
        LOG.info(name + " timer ran for " + (end - start) + "ms");
        return end - start;
    }
}

Якщо ви намагаєтесь зупинити неіснуючий таймер або той, який уже зупинений, це має бути помилкою, а не ігноруватися.
Позов до Моніки

@QPaysTaxes - Залежить від вашого наміру. Якщо вам потрібна полегшена утиліта, якою можна легко користуватися, ви, як правило , не хочете бути throw Exceptionпоруч. Крім того, це не те, що спроба зупинити неіснуючий або вже зупинений таймер - це те, що абонент, як правило, може відновити.
aroth

1

Інший приклад: я використовую його для групування даних за датою. Але деякі дані не мають дати. Я можу згрупувати його за допомогою заголовка "NoDate"


0

Нульовий ключ також може бути корисним, коли карта зберігає дані для вибору інтерфейсу користувача, де ключ карти представляє поле компонента.

Відповідне значення нульового поля, наприклад, буде представлене як "(будь ласка, виберіть)" у виборі інтерфейсу користувача.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.