Как обновить значение, заданное ключом в Java hashmap?

предположим, что у нас есть HashMap<String, Integer> в Java.

Как обновить (увеличить) целое значение строкового ключа для каждого существования строки, которую я нахожу?

можно удалить и снова войти в пару, но накладные расходы будут проблемой.
Другой способ - просто поставить новую пару, и старая будет заменена.

в последнем случае, что произойдет, если произойдет столкновение хэш-кода с новым ключом, который я пытаюсь вставить? Правильное поведение hashtable было бы назначить другое место для него или сделать список из него в текущем ведре.

16 ответов


map.put(key, map.get(key) + 1);

должно быть нормально. Он обновит значение для существующего сопоставления. Обратите внимание, что это использует auto-boxing.


Java 8 способ:

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

например,

Map<String, Integer> words = new HashMap<>();
words.put("hello", 3);
words.put("world", 4);
words.computeIfPresent("hello", (k, v) -> v + 1);
System.out.println(words.get("hello"));

то обводняться, то можно использовать merge метод, где 1-значение по умолчанию, а функция увеличивает существующее значение на 1:

words.merge("hello", 1, Integer::sum);

кроме того, есть куча других полезных методов, таких как putIfAbsent, getOrDefault, forEach, etc.


hashmap.put(key, hashmap.get(key) + 1);

метод put будет заменить значение существующего ключа и создать его, если не существует.


заменить Integer by AtomicInteger и позвоните одному из incrementAndGet/getAndIncrement методы на нем.

альтернативой является обертывание int в своем MutableInteger класс, который имеет increment() метод, у вас есть только threadsafety озабоченность, чтобы решить еще.


упрощенная Java 8 путь:

map.put(key, map.getOrDefault(key, 0) + 1);

Это использует метод HashMap, который извлекает значение для ключа, но если ключ не может быть извлечен, он возвращает указанное значение по умолчанию (в этом случае "0").

это поддерживается в core Java:хранилище HashMap getOrDefault(ключевой объект, в значение по умолчанию)


@ Matthew'S решение является самым простым и будет работать достаточно хорошо в большинстве случаев.

Если вам нужна высокая производительность, AtomicInteger-лучшее решение ala @BalusC.

однако более быстрое решение (при условии, что безопасность потока не является проблемой) - использовать TObjectIntHashMap который предоставляет метод инкремента (ключа) и использует примитивы и меньше объектов, чем создание AtomicIntegers. например,

TObjectIntHashMap<String> map = new TObjectIntHashMap<String>()
map.increment("aaa");

решение одной строки:

map.put(key, map.containsKey(key) ? map.get(key) + 1 : 1);

вы можете увеличить, как показано ниже, но вам нужно проверить наличие, чтобы исключение NullPointerException не бросалось

if(!map.containsKey(key)) {
 p.put(key,1);
}
else {
 p.put(key, map.getKey()+1);
}

существует ли хэш (с 0 в качестве значения) или он" помещен " на карту при первом приращении? Если он" поставлен " на первом приращении, код должен выглядеть так:

if (hashmap.containsKey(key)) {
    hashmap.put(key, hashmap.get(key)+1);
} else { 
    hashmap.put(key,1);
}

это может быть немного поздно, но вот мои два цента.

если вы используете Java 8, то вы можете использовать computeIfPresent метод. Если значение для указанного ключа присутствует и не равно null, то он пытается вычислить новое сопоставление с учетом ключа и его текущего сопоставленного значения.

final Map<String,Integer> map1 = new HashMap<>();
map1.put("A",0);
map1.put("B",0);
map1.computeIfPresent("B",(k,v)->v+1);  //[A=0, B=1]

мы также можем использовать другой метод putIfAbsent поставить ключ. Если указанный ключ уже не связывается со значением (или подключенный к нулю), то этот метод связывает его с заданным значением и возвращает null, иначе возвращает текущее значение.

в случае, если карта разделена между потоками, мы можем использовать ConcurrentHashMap и AtomicInteger. От Дока:

An AtomicInteger значение int, которое может быть обновлено автоматически. - AtomicInteger используется в приложениях, таких как атомарно увеличенный счетчики, и не может использоваться в качестве замены для целое. Однако, этот класс расширяет число, чтобы обеспечить единообразный доступ инструментов и утилиты, которые имеют дело с числовыми классами.

мы можем использовать их, как показано ниже:

final Map<String,AtomicInteger> map2 = new ConcurrentHashMap<>();
map2.putIfAbsent("A",new AtomicInteger(0));
map2.putIfAbsent("B",new AtomicInteger(0)); //[A=0, B=0]
map2.get("B").incrementAndGet();    //[A=0, B=1]

один момент, чтобы наблюдать, мы призываем get чтобы получить значение для ключа B и тогда вызов incrementAndGet() о его значении, которое, конечно,AtomicInteger. Мы можем оптимизировать его как метод putIfAbsent возвращает значение ключа, если уже присутствует:

map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]

на a примечание, если мы планируем использовать AtomicLong тогда в соответствии с документацией при высокой конкуренции ожидаемая пропускная способность LongAdder значительно выше, за счет более высокого потребления пространства. Также проверьте это вопрос.


более чистое решение без исключения NullPointerException:

map.replace(key, map.get(key) + 1);

использовать for цикл для увеличения индекса:

for (int i =0; i<5; i++){
    HashMap<String, Integer> map = new HashMap<String, Integer>();
    map.put("beer", 100);

    int beer = map.get("beer")+i;
    System.out.println("beer " + beer);
    System.out ....

}

здесь есть вводящие в заблуждение ответы на этот вопрос, которые подразумевают, что метод Hashtable put заменит существующее значение, если ключ существует, это верно не для Hashtable, а для HashMap. См. Javadoc для HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29


поскольку я не могу прокомментировать несколько ответов из-за меньшей репутации, я опубликую решение, которое я применил.

for(String key : someArray)
{
   if(hashMap.containsKey(key)//will check if a particular key exist or not 
   {
      hashMap.put(hashMap.get(key),value+1);// increment the value by 1 to an already existing key
   }
   else
   {
      hashMap.put(key,value);// make a new entry into the hashmap
   }
}

попробуй:

HashMap hm=new HashMap<String ,Double >();

Примечание:

String->give the new value; //THIS IS THE KEY
else
Double->pass new value; //THIS IS THE VALUE

вы можете изменить ключ или значение в вашем hashmap, но вы не можете изменить оба одновременно.


Integer i = map.get(key);
if(i == null)
   i = (aValue)
map.put(key, i + 1);

или

Integer i = map.get(key);
map.put(key, i == null ? newValue : i + 1);

Integer-это примитивные типы данных http://cs.fit.edu / ~ryan/java/language/java-data.html, поэтому вам нужно принять его вне, сделать некоторый процесс, тогда положите его назад. если у вас есть значение, которое не является примитивными типами данных, вам нужно только вынуть его, обработать его, не нужно возвращать его в hashmap.