Хэш-карты Java без значения? - PullRequest
24 голосов
/ 13 мая 2009

Допустим, я хочу поместить слова в структуру данных, и я хочу иметь постоянный поиск времени, чтобы увидеть, находится ли слово в этой структуре данных. Все, что я хочу сделать, это посмотреть, существует ли это слово. Буду ли я использовать HashMap (containsKey ()) для этого? HashMap s используют пары ключ-> значение, но в моем случае у меня нет значения. Конечно, я мог бы использовать ноль для значения, но даже нуль занимает место. Похоже, что для этого приложения должна быть лучшая структура данных.

Коллекция потенциально может использоваться несколькими потоками, но поскольку объекты, содержащиеся в коллекции, не изменятся, я не думаю, что у меня есть требование синхронизации / параллелизма.

Кто-нибудь может мне помочь?

Ответы [ 6 ]

44 голосов
/ 13 мая 2009

Используйте взамен HashSet . Это хеш-реализация Set , которая используется в основном для того, что вы описываете (неупорядоченный набор элементов).

7 голосов
/ 13 мая 2009

Обычно вы используете реализацию Set , и чаще всего HashSet. Если вам действительно нужен параллельный доступ, то ConcurrentHashSet предоставляет замену, которая обеспечивает безопасный параллельный доступ, включая безопасную итерацию по набору.

Я бы порекомендовал в любом случае ссылаться на него как на просто Set во всем вашем коде, за исключением одного места, где вы его создаете; таким образом, проще внедрить одну реализацию для другой, если позже она понадобится.

Даже если набор доступен только для чтения , если он используется потоком, отличным от того, который его создает, вам нужно подумать о safe публикации (то есть, чтобы убедиться, что любой другой поток видит набор в непротиворечивом состоянии: помните, что любые записи в память, даже в конструкторы, не гарантированно будут доступны другим потокам, когда вы ожидаете или в другом порядке, если вы принять меры для обеспечения этого). Это можно сделать одним из следующих способов:

  • убедившись, что единственная ссылка (и) на набор находится в конечных полях ;
  • убедившись, что действительно верно, что ни один поток не изменяет набор.

Вы можете помочь в этом, используя оболочку Collections.unmodifiableSet (). Это дает вам неизменяемое представление данного набора - так что при отсутствии других «нормальных» ссылок на наборы вы можете быть в безопасности.

7 голосов
/ 13 мая 2009

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

Даже если объекты, содержащиеся в коллекции, не изменяются, вам может потребоваться выполнить синхронизацию. Нужно ли добавлять новые объекты в набор после передачи набора в другой поток? Если это так, вы можете использовать Collections.synchronizedSet () , чтобы сделать Set потокобезопасным.

Если у вас есть Карта со значениями, и у вас есть код, который просто хочет рассматривать Карту как Набор, вы можете использовать Map.entrySet () (хотя имейте в виду, что entrySet возвращает представление Set ключей Карта; если Карта изменчива, Карта может быть изменена с помощью набора, возвращенного entrySet).

6 голосов
/ 13 мая 2009

Вы хотите использовать Collection, реализующий интерфейс Set, возможно, HashSet, чтобы получить заявленную производительность. Смотри http://java.sun.com/javase/6/docs/api/java/util/Set.html

1 голос
/ 13 мая 2009

Кроме Set s, в некоторых случаях вы можете преобразовать Map в Set с Collections.newSetFromMap(Map<E,Boolean>) (некоторые Map s запрещают null значения, следовательно, Boolean).

0 голосов
/ 13 мая 2009

как все говорили, HashSet, вероятно, самое простое решение, но у вас не будет постоянного поиска в HashSet (потому что записи могут быть связаны), и вы будете хранить фиктивный объект (всегда одинаковый) для каждой записи ...

Для получения информации вот список структур данных возможно, вы найдете такую, которая лучше соответствует вашим потребностям.

...