containsKey
, put
и get
. Это самый популярный предварительно Java 8 один, хотя его самый неэффективный из этого списка, поскольку она включает в себя до трех хэш-запросов для того же ключа
String key=str.substring(i, j);
if(!map.containsKey(key))
map.put(key, new HashSet<>());
map.get(key).add(str);
get
и put
. Лучше, чем первый, хотя он все еще может включать два поиска. Для обычных Map
с, это был лучший выбор, прежде чем Java 8:
String key=str.substring(i, j);
Set<String> set=map.get(key);
if(set==null)
map.put(key, set=new HashSet<>());
set.add(str);
putIfAbsent
. До Java 8 эта опция была доступна только ConcurrentMap
.
String key=str.substring(i, j);
Set<String> set=new HashSet<>(), old=map.putIfAbsent(key, set);
(old!=null? old: set).add(str);
Это только имеет один хэш-поиск, но требует безусловного создания нового HashSet
, даже если она не нужна. Здесь может стоить выполнить сначала get
, чтобы отложить создание, особенно при использовании ConcurrentMap
, поскольку get
может быть выполнен без блокировки и может сделать последующие более дорогостоящие putIfAbsent
ненужными.
С другой стороны, необходимо подчеркнуть, что эта конструкция не является потокобезопасной, поскольку манипуляция значением Set
не защищена ничем.
computeIfAbsent
.Этот 8 метод Java позволяет наиболее краткую и наиболее эффективную работу:
map.computeIfAbsent(str.substring(i, j), k -> new HashSet<>()).add(str);
Это будет только оценить функцию, если нет старого значения, и в отличие от putIfAbsent
, этот метод возвращает новое значение, если не было старых Другими словами, он возвращает право Set
в любом случае, поэтому мы можем напрямую add
. Тем не менее, операция add
выполняется за пределами операции Map
, поэтому нет безопасности нитей, даже если Map
является потокобезопасным. Но для обычных Map
с, то есть если безопасность потока не является проблемой, это наиболее эффективный вариант.
compute
. Этот Java-метод всегда будет оценивать функцию и может использоваться двумя способами. Первый
map.compute(str.substring(i, j), (k,v) -> v==null? new HashSet<>(): v).add(str);
это просто более подробный вариант computeIfAbsent
. Второй
map.compute(str.substring(i, j), (k,v) -> {
if(v==null) v=new HashSet<>();
v.add(str);
return v;
});
выполнит Set
обновления в соответствии с политикой безопасности нити в Map
«с, так что в случае ConcurrentHashMap
, это будет поточно обновление, поэтому использование compute
вместо computeIfAbsent
имеет действительный случай использования когда нить безопасность - это проблема.
Что такое NPE? Это 'str',' map' или return 'putIfAbsent'? – 4castle
Быстрый взгляд на javadoc говорит, что 'putIfAbsent' возвращает null, когда этот ключ еще не на карте. Вы рассматривали эту возможность перед вызовом add()? –
Почему, по-вашему, вам нужно выбирать между этими двумя методами? Для этой цели существует не менее четырех методов, не считая неуместного, который вы указали. – Holger