ConcurrentHashMap.newKeySet() vs Collections.newSetFromMap()
Java 8 представила новый способ получения параллельной реализации Set
// Pre-Java-8 way to create a concurrent set
Set<String> oldStyle = Collections.newSetFromMap(new ConcurrentHashMap<>());
// New method in Java 8
Set<String> newStyle = ConcurrentHashMap.newKeySet();
Есть ли причина предпочитать новый метод?
Любые преимущества/недостатки?
Ответы
Ответ 1
ConcurrentHashMap.newKeySet()
должен быть несколько более эффективным, поскольку удаляет один уровень косвенности. Collections.newSetFromMap(map)
в основном основана на перенаправлении операций на map.keySet()
, но ConcurrentHashMap.newKeySet()
очень близок к map.keySet()
(только с поддержкой дополнений).
Что касается функциональности, я не вижу разницы.
Ответ 2
ConcurrentHashMap.newKeySet()
- это всего лишь часть функции, которая намного шире, чем Collections.newSetFromMap(new ConcurrentHashMap<>())
.
Разница становится понятной, если вы посмотрите на этот пример:
Set<String> set=new ConcurrentHashMap<String,String>().keySet("hello");
Вместо сопоставления с Boolean.TRUE
вы добавляете значение "hello"
при добавлении нового значения в Set
.
Вот почему возвращаемый Set
имеет тип ConcurrentHashMap.KeySetView
. У этого типа есть дополнительные методы для запроса карты поддержки, а также какое значение будет использовано при добавлении новых ключей.
Таким образом, хотя ConcurrentHashMap.newKeySet()
выглядит так же, как Collections.newSetFromMap(new ConcurrentHashMap<>())
, существует семантическая разница, которая, по словам последнего, не должна использовать карту впоследствии, в то время как первая является частью функции, которая предназначен для взаимодействия с картой.
См. Collections.newSetFromMap
:
Указанная карта должна быть пустой во время вызова этого метода и не должна быть доступна сразу после возвращения этого метода.
На самом деле, даже не указано, что Collections.newSetFromMap
будет использовать Boolean.TRUE
для добавленных значений - вы никогда не должны иметь дело с этим в любом случае...
Это также может быть полезно, когда вы хотите передать Set
для кода, который явно запрашивает ConcurrentHashMap.KeySetView
.
Если вы используете результат только с использованием типа времени компиляции Set
only, существует вероятность того, что код, получающий этот Set
будет использовать instanceof
/type, чтобы узнать, что результат ConcurrentHashMap.newKeySet()
поддерживается ConcurrentHashMap
тогда как результат Collections.newSetFromMap
скажет вам. С другой стороны, это также позволяет коду делать непреднамеренные вещи с поддержкой карты таким образом...