HashSet основан на HashMap.
Если мы посмотрим на HashSet<E>
реализацию, все было под управлением HashMap<E,Object>
.
<E>
используется в качестве ключа HashMap
.
И мы знаем, что HashMap
это не потокобезопасно. Вот почему у нас ConcurrentHashMap
в Java.
Исходя из этого, я запутался, что почему у нас нет ConcurrentHashSet, который должен основываться на ConcurrentHashMap
?
Есть ли что-то еще, что мне не хватает? Мне нужно использовать Set
в многопоточной среде.
Кроме того , если я хочу , чтобы создать свой собственный ConcurrentHashSet
я могу добиться этого, просто заменив HashMap
на ConcurrentHashMap
и оставить остальное как есть?
java
collections
concurrency
hashmap
hashset
Талха Ахмед Хан
источник
источник
ConcurrentSkipListSet
на томConcurrentSkipListMap
, что реализуетConcurrentNavigableMap
иConcurrentMap
.Ответы:
Там нет встроенного типа для,
ConcurrentHashSet
потому что вы всегда можете извлечь набор из карты. Поскольку существует много типов карт, вы используете метод для создания набора из данной карты (или класса карты).До Java 8 вы создавали параллельный хеш-набор, поддерживаемый одновременной хэш-картой, используя
Collections.newSetFromMap(map)
В Java 8 (указанный) @ Matt, вы можете получить одновременный хэш набор вида через
ConcurrentHashMap.newKeySet()
. Это немного проще, чем старый,newSetFromMap
который требовал от вас передать пустой объект карты. Но это специфично дляConcurrentHashMap
.В любом случае, разработчики Java могли создавать новый интерфейс набора каждый раз, когда создавался новый интерфейс карты, но этот шаблон было бы невозможно применить, когда третьи стороны создают свои собственные карты. Лучше иметь статические методы, которые получают новые наборы; этот подход всегда работает, даже когда вы создаете свои собственные реализации карт.
источник
ConcurrentHashMap
, вы потеряете те преимущества, которые получили быConcurrentHashMap
?newSetFromMap
Реализация начинается со строки 3841 в docjar.com/html/api/java/util/Collections.java.html . Это просто обертка ....Collections.newSetFromMap
создаетSetFromMap
. например,SetFromMap.removeAll
метод делегирует тоKeySetView.removeAll
, что наследуется отConcurrentHashMap$CollectionView.removeAll
. Этот метод крайне неэффективен при удалении большого количества элементов. Представьте, что выremoveAll(Collections.emptySet())
пересекаете все элементы,Map
ничего не делая. ИмеяConcurrentHashSet
что corretly реализован будет лучше в большинстве случаев.источник
С Guava 15 вы также можете просто использовать:
источник
Как упомянул Рэй Тоал, это так же просто, как:
источник
ConcurrentHashMap
.Похоже, что Java предоставляет параллельную реализацию Set со своим ConcurrentSkipListSet . Набор SkipList - это просто особая реализация набора. Он по-прежнему реализует интерфейсы Serializable, Cloneable, Iterable, Collection, NavigableSet, Set, SortedSet. Это может работать для вас, если вам нужен только интерфейс Set.
источник
ConcurrentSkipListSet
элементы должны бытьComparable
ConcurrentSkipListSet
если вы не хотитеSortedSet
. Обычная операция, такая как add или remove, должна быть O (1) для aHashSet
, но O (log (n)) для aSortedSet
.Как указано на это лучший способ , чтобы получить параллелизм-возможность HashSet это с помощью
Collections.synchronizedSet()
Это сработало для меня, и я не видел, чтобы кто-то действительно указывал на это.
РЕДАКТИРОВАТЬ Это менее эффективно, чем одобренное в настоящее время решение, как отмечает Юджин, поскольку оно просто оборачивает ваш набор в синхронизированный декоратор, в то время как
ConcurrentHashMap
фактически реализует низкоуровневый параллелизм и может поддерживать ваш Set так же хорошо. Так что спасибо г-ну Степаненкову за то, что он это прояснил.http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-
источник
synchronizedSet
метод просто создает декоратор подCollection
методы обертки , которые могут быть поточно-синхронизацией всей коллекции. НоConcurrentHashMap
реализован с использованием неблокирующих алгоритмов и «низкоуровневых» синхронизаций без каких-либо блокировок всей коллекции. Так что переносчики изCollections.synchronized
... хуже в многопоточных средах по соображениям производительности.Вы можете использовать гуаву,
Sets.newSetFromMap(map)
чтобы получить один. Java 6 также имеет этот метод вjava.util.Collections
источник
источник
Почему бы не использовать: CopyOnWriteArraySet из java.util.concurrent?
источник