Хорошо ли хранить данные в виде ключей в HashMap с пустыми/нулевыми значениями?

Я изначально написал ArrayList и сохранил уникальные значения (имена пользователей, т.е. Strings). Позднее мне понадобилось использовать ArrayList для поиска, если пользователь существовал в нем. Это O(n) для поиска.

Мой технический руководитель хотел, чтобы я изменил его на HashMap и сохранил имена пользователей как ключи в массиве, а значения пустые Strings.

Итак, в Java -

hashmap.put("johndoe","");

Я вижу, существует ли этот пользователь позже, выполнив -

hashmap.containsKey("johndoe"); 

Это O(1) правильно?

Мой руководитель сказал, что это был более эффективный способ сделать это, и это имело смысл для меня, но мне показалось, что это немного пошло, чтобы поместить null/empty в качестве значений в hashmap и сохранить в нем элементы как ключи.

Мой вопрос в том, хороший подход? Эффективность превосходит ArrayList#contains или поиск массива в целом. Оно работает. Мое беспокойство заключается в том, что я не видел, чтобы кто-то еще делал это после обыска. Возможно, я не вижу очевидной проблемы, но я не вижу ее.

Ответ 1

Поскольку у вас есть набор уникальных значений, Set - соответствующая структура данных. Вы можете поместить свои значения в HashSet, реализацию интерфейса Set.

Мой руководитель сказал, что это был более эффективный способ сделать это, и это имело смысл для меня, но мне показалось, что это немного пошло, чтобы поместить null/empty в качестве значений в hashmap и сохранить в нем элементы как ключи.

Совет по свинцу является ошибочным. Map не является правильной абстракцией для этого, Set is. A Map подходит для пар ключ-значение. Но у вас нет значений, только ключей.

Пример использования:

Set<String> users = new HashSet<>(Arrays.asList("Alice", "Bob"));

System.out.println(users.contains("Alice"));
// -> prints true

System.out.println(users.contains("Jack"));
// -> prints false

Использование Map было бы неудобным, потому что какой должен быть тип значений? Этот вопрос не имеет смысла в вашем случае использования, поскольку у вас есть только ключи, а не пары ключ-значение. С Set вам не нужно спрашивать об этом, использование совершенно естественно.

Это O (1) правильно?

Да, поиск в HashMap или HashSet является O (1) амортизированным наихудшим случаем, тогда как поиск в List или в массиве - это O (n) наихудший случай.


В некоторых комментариях указывается, что a HashSet реализуется в терминах HashMap. Это прекрасно, на этом уровне абстракции. На уровне абстракции задачи под рукой --- для хранения коллекции уникальных имен пользователей, использование набора является естественным выбором, более естественным, чем карта.

Ответ 2

В основном это реализация HashSet, поэтому, я думаю, вы можете сказать, что это хороший подход. Вы можете использовать HashSet вместо HashMap с пустыми значениями.

Например:

HashSet реализация add -

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

где map - это поддержка HashMap, а PRESENT - фиктивное значение.

Мое беспокойство заключается в том, что я не видел, чтобы кто-то еще делал это после поиска. Возможно, я не вижу очевидной проблемы, но я не вижу ее.

Как я уже упоминал, разработчики JDK используют этот же подход.