Как обновить значение, учитывая ключ в java hashmap?
предположим, что у нас есть HashMap<String, Integer> в Java.
Как обновить (увеличить) целочисленное значение строкового ключа для каждого существования строки, которую я нахожу?
можно было бы удалить и повторно ввести пару, но накладные расходы были бы проблемой.
Другой способ - просто поставить новую пару, а старую заменить.
в последнем случае, что произойдет, если произойдет столкновение хэш-кода с новым ключом, который я пытаюсь вставить? Правильное поведение hashtable будет назначать другое место для него или составлять список из него в текущем ведре.
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будет заменить значение существующего ключа и создать его, если не существует.
заменить
IntegerbyAtomicIntegerи позвоните одному из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");
вы можете увеличить, как показано ниже, но вам нужно проверить наличие так, чтобы 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 значительно выше, за счет более высокого потребления пространства. Также проверьте это вопрос.
использовать
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