Как обновить значение, учитывая ключ в java hashmap?



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



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



можно было бы удалить и повторно ввести пару, но накладные расходы были бы проблемой.

Другой способ - просто поставить новую пару, а старую заменить.



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

905   16  

16 ответов:

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

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

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 и т. д.

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').

это поддерживается в ядре Java: HashMap getOrDefault (Object key, V defaultValue)

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

Если вам нужна высокая производительность, 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, так что вам нужно вынуть его, сделать какой-то процесс, а затем положить его обратно. если у вас есть значение, которое не является примитивными типами данных, вам нужно только вынуть его, обработать его, не нужно возвращать его в хэш-карту.

Comments

    Ничего не найдено.