如何更新java hashmap中的键值?

时间:2022-06-17 19:17:12

Suppose we have a HashMap<String, Integer> in Java.

假设我们有一个HashMap 在Java中。 ,>

How do I update (increment) the integer-value of the string-key for each existence of the string I find?

对于我找到的每个字符串的存在,我如何更新(增加)字符串键的整数值?

One could remove and reenter the pair, but overhead would be a concern.
Another way would be to just put the new pair and the old one would be replaced.

可以删除和重新输入这一对,但是开销可能是一个问题。另一种方法是把新的和旧的替换掉。

In the latter case, what happens if there is a hashcode collision with a new key I am trying to insert? The correct behavior for a hashtable would be to assign a different place for it, or make a list out of it in the current bucket.

在后一种情况下,如果hashcode与要插入的新键发生冲突,会发生什么情况?哈希表的正确行为应该是为它分配一个不同的位置,或者在当前的桶中列出一个列表。

16 个解决方案

#1


719  

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

should be fine. It will update the value for the existing mapping. Note that this uses auto-boxing.

应该没事的。它将更新现有映射的值。注意,这使用了自动装箱。

#2


63  

Java 8 way:

You can use computeIfPresent method and supply it a mapping function, which will be called to compute a new value based on existing one.

您可以使用computeIfPresent方法并向它提供一个映射函数,该函数将根据现有的值调用来计算新的值。

For example,

例如,

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"));

Alternatevely, you could use merge method, where 1 is the default value and function increments existing value by 1:

另外,可以使用merge method,其中1为默认值,函数将现有值增加1:

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

In addition, there is a bunch of other useful methods, such as putIfAbsent, getOrDefault, forEach, etc.

此外,还有许多其他有用的方法,如putIfAbsent、getOrDefault、forEach等。

#3


41  

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

The method put will replace the value of an existing key and will create it if doesn't exist.

put方法将替换现有键的值,如果不存在则创建它。

#4


25  

Replace Integer by AtomicInteger and call one of the incrementAndGet/getAndIncrement methods on it.

用AtomicInteger替换Integer,并调用其中一个incrementAndGet/getAndIncrement方法。

An alternative is to wrap an int in your own MutableInteger class which has an increment() method, you only have a threadsafety concern to solve yet.

另一种方法是在您自己的MutableInteger类中包装一个int,它有一个increment()方法,您只需要解决一个threadsafety问题。

#5


16  

@Matthew's solution is the simplest and will perform well enough in most cases.

@Matthew的解决方案是最简单的,在大多数情况下都足够好。

If you need high performance, AtomicInteger is a better solution ala @BalusC.

如果您需要高性能,AtomicInteger是更好的ala @BalusC解决方案。

However, a faster solution (provided thread safety is not an issue) is to use TObjectIntHashMap which provides a increment(key) method and uses primitives and less objects than creating AtomicIntegers. e.g.

但是,更快的解决方案(提供线程安全不是问题)是使用TObjectIntHashMap,它提供了一个增量(键)方法,并使用原语和更少的对象,而不是创建atomicinteger。如。

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

#6


14  

The simplified Java 8 way:

简化的Java 8方法:

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

This uses the method of HashMap that retrieves the value for a key, but if the key can't be retrieved it returns the specified default value (in this case a '0').

这使用HashMap方法检索键的值,但是如果无法检索键,则返回指定的默认值(在本例中为“0”)。

This is supported within core Java: HashMap<K,V> getOrDefault(Object key, V defaultValue)

这在核心Java中得到支持:HashMap getOrDefault(对象键,V defaultValue) ,v>

#7


12  

One line solution:

一行的解决方案:

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

#8


11  

You can increment like below but you need to check for existence so that a NullPointerException is not thrown

可以像下面这样递增,但是需要检查是否存在,这样就不会抛出NullPointerException

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

#9


8  

Does the hash exist (with 0 as the value) or is it "put" to the map on the first increment? If it is "put" on the first increment, the code should look like:

散列是否存在(以0为值),还是在第一个增量上“放入”到映射?如果在第一个增量上“放置”,则代码应如下:

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

#10


5  

It may be little late but here are my two cents.

可能有点晚了,但这是我的两点意见。

If you are using Java 8 then you can make use of computeIfPresent method. If the value for the specified key is present and non-null then it attempts to compute a new mapping given the key and its current mapped value.

如果您正在使用Java 8,那么您可以使用computeIfPresent方法。如果指定键的值为当前和非空值,那么它将尝试计算给定键和当前映射值的新映射。

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]

We can also make use of another method putIfAbsent to put a key. If the specified key is not already associated with a value (or is mapped to null) then this method associates it with the given value and returns null, else returns the current value.

我们还可以利用另一种方法putIfAbsent来放置密钥。如果指定的键尚未与值关联(或映射为null),则此方法将其与给定值关联并返回null,否则返回当前值。

In case the map is shared across threads then we can make use of ConcurrentHashMap and AtomicInteger. From the doc:

如果映射是跨线程共享的,那么我们可以使用ConcurrentHashMap和AtomicInteger。从医生:

An AtomicInteger is an int value that may be updated atomically. An AtomicInteger is used in applications such as atomically incremented counters, and cannot be used as a replacement for an Integer. However, this class does extend Number to allow uniform access by tools and utilities that deal with numerically-based classes.

AtomicInteger是可以以原子方式更新的int值。AtomicInteger用于诸如原子递增计数器之类的应用程序,不能用于替换整数。但是,这个类确实扩展了Number,允许处理基于数字的类的工具和实用程序进行统一访问。

We can use them as shown:

我们可以使用它们,如下所示:

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]

One point to observe is we are invoking get to get the value for key B and then invoking incrementAndGet() on its value which is of course AtomicInteger. We can optimize it as the method putIfAbsent returns the value for the key if already present:

需要注意的一点是,我们调用get来获取密钥B的值,然后调用incrementAndGet()来调用它的值,当然是AtomicInteger。我们可以将其优化为putifabsend方法返回的值,如果已经存在的话:

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

On a side note if we plan to use AtomicLong then as per documentation under high contention expected throughput of LongAdder is significantly higher, at the expense of higher space consumption. Also check this question.

另一方面,如果我们计划使用AtomicLong,那么根据高争用的文档,LongAdder的预期吞吐量将显著提高,代价是更高的空间消耗。还要检查这个问题。

#11


1  

Use a for loop to increment the index:

使用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 ....

}

#12


1  

There are misleading answers to this question here that imply Hashtable put method will replace the existing value if the key exists, this is not true for Hashtable but rather for HashMap. See Javadoc for HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29

这里有对这个问题的误导回答,暗示如果键存在,Hashtable put方法将替换现有值,但对Hashtable不是这样,而是HashMap。请参阅Javadoc获取HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29

#13


1  

The cleaner solution without NullPointerException is:

没有NullPointerException的更清洁的解决方案是:

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

#14


0  

Try:

试一试:

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

NOTE:

注意:

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

You can change either the key or the value in your hashmap, but you can't change both at the same time.

您可以更改hashmap中的键或值,但不能同时更改这两个键或值。

#15


0  

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

or

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

Integer is Primitive data types http://cs.fit.edu/~ryan/java/language/java-data.html, so you need to take it out, make some process, then put it back. if you have a value which is not Primitive data types, you only need to take it out, process it, no need to put it back into the hashmap.

Integer是原始数据类型http://cs.fit.edu/~ryan/java/language/java /java-data.html,所以需要取出它,做一些处理,然后再放回去。如果你有一个不是原始数据类型的值,你只需要取出它,处理它,不需要把它放回hashmap中。

#16


0  

Since I can't comment to a few answers due to less reputation, I will post a solution which I applied.

由于声誉不好,我无法对一些答案进行评论,所以我将发布一个我应用的解决方案。

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
   }
}

#1


719  

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

should be fine. It will update the value for the existing mapping. Note that this uses auto-boxing.

应该没事的。它将更新现有映射的值。注意,这使用了自动装箱。

#2


63  

Java 8 way:

You can use computeIfPresent method and supply it a mapping function, which will be called to compute a new value based on existing one.

您可以使用computeIfPresent方法并向它提供一个映射函数,该函数将根据现有的值调用来计算新的值。

For example,

例如,

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"));

Alternatevely, you could use merge method, where 1 is the default value and function increments existing value by 1:

另外,可以使用merge method,其中1为默认值,函数将现有值增加1:

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

In addition, there is a bunch of other useful methods, such as putIfAbsent, getOrDefault, forEach, etc.

此外,还有许多其他有用的方法,如putIfAbsent、getOrDefault、forEach等。

#3


41  

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

The method put will replace the value of an existing key and will create it if doesn't exist.

put方法将替换现有键的值,如果不存在则创建它。

#4


25  

Replace Integer by AtomicInteger and call one of the incrementAndGet/getAndIncrement methods on it.

用AtomicInteger替换Integer,并调用其中一个incrementAndGet/getAndIncrement方法。

An alternative is to wrap an int in your own MutableInteger class which has an increment() method, you only have a threadsafety concern to solve yet.

另一种方法是在您自己的MutableInteger类中包装一个int,它有一个increment()方法,您只需要解决一个threadsafety问题。

#5


16  

@Matthew's solution is the simplest and will perform well enough in most cases.

@Matthew的解决方案是最简单的,在大多数情况下都足够好。

If you need high performance, AtomicInteger is a better solution ala @BalusC.

如果您需要高性能,AtomicInteger是更好的ala @BalusC解决方案。

However, a faster solution (provided thread safety is not an issue) is to use TObjectIntHashMap which provides a increment(key) method and uses primitives and less objects than creating AtomicIntegers. e.g.

但是,更快的解决方案(提供线程安全不是问题)是使用TObjectIntHashMap,它提供了一个增量(键)方法,并使用原语和更少的对象,而不是创建atomicinteger。如。

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

#6


14  

The simplified Java 8 way:

简化的Java 8方法:

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

This uses the method of HashMap that retrieves the value for a key, but if the key can't be retrieved it returns the specified default value (in this case a '0').

这使用HashMap方法检索键的值,但是如果无法检索键,则返回指定的默认值(在本例中为“0”)。

This is supported within core Java: HashMap<K,V> getOrDefault(Object key, V defaultValue)

这在核心Java中得到支持:HashMap getOrDefault(对象键,V defaultValue) ,v>

#7


12  

One line solution:

一行的解决方案:

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

#8


11  

You can increment like below but you need to check for existence so that a NullPointerException is not thrown

可以像下面这样递增,但是需要检查是否存在,这样就不会抛出NullPointerException

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

#9


8  

Does the hash exist (with 0 as the value) or is it "put" to the map on the first increment? If it is "put" on the first increment, the code should look like:

散列是否存在(以0为值),还是在第一个增量上“放入”到映射?如果在第一个增量上“放置”,则代码应如下:

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

#10


5  

It may be little late but here are my two cents.

可能有点晚了,但这是我的两点意见。

If you are using Java 8 then you can make use of computeIfPresent method. If the value for the specified key is present and non-null then it attempts to compute a new mapping given the key and its current mapped value.

如果您正在使用Java 8,那么您可以使用computeIfPresent方法。如果指定键的值为当前和非空值,那么它将尝试计算给定键和当前映射值的新映射。

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]

We can also make use of another method putIfAbsent to put a key. If the specified key is not already associated with a value (or is mapped to null) then this method associates it with the given value and returns null, else returns the current value.

我们还可以利用另一种方法putIfAbsent来放置密钥。如果指定的键尚未与值关联(或映射为null),则此方法将其与给定值关联并返回null,否则返回当前值。

In case the map is shared across threads then we can make use of ConcurrentHashMap and AtomicInteger. From the doc:

如果映射是跨线程共享的,那么我们可以使用ConcurrentHashMap和AtomicInteger。从医生:

An AtomicInteger is an int value that may be updated atomically. An AtomicInteger is used in applications such as atomically incremented counters, and cannot be used as a replacement for an Integer. However, this class does extend Number to allow uniform access by tools and utilities that deal with numerically-based classes.

AtomicInteger是可以以原子方式更新的int值。AtomicInteger用于诸如原子递增计数器之类的应用程序,不能用于替换整数。但是,这个类确实扩展了Number,允许处理基于数字的类的工具和实用程序进行统一访问。

We can use them as shown:

我们可以使用它们,如下所示:

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]

One point to observe is we are invoking get to get the value for key B and then invoking incrementAndGet() on its value which is of course AtomicInteger. We can optimize it as the method putIfAbsent returns the value for the key if already present:

需要注意的一点是,我们调用get来获取密钥B的值,然后调用incrementAndGet()来调用它的值,当然是AtomicInteger。我们可以将其优化为putifabsend方法返回的值,如果已经存在的话:

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

On a side note if we plan to use AtomicLong then as per documentation under high contention expected throughput of LongAdder is significantly higher, at the expense of higher space consumption. Also check this question.

另一方面,如果我们计划使用AtomicLong,那么根据高争用的文档,LongAdder的预期吞吐量将显著提高,代价是更高的空间消耗。还要检查这个问题。

#11


1  

Use a for loop to increment the index:

使用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 ....

}

#12


1  

There are misleading answers to this question here that imply Hashtable put method will replace the existing value if the key exists, this is not true for Hashtable but rather for HashMap. See Javadoc for HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29

这里有对这个问题的误导回答,暗示如果键存在,Hashtable put方法将替换现有值,但对Hashtable不是这样,而是HashMap。请参阅Javadoc获取HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29

#13


1  

The cleaner solution without NullPointerException is:

没有NullPointerException的更清洁的解决方案是:

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

#14


0  

Try:

试一试:

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

NOTE:

注意:

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

You can change either the key or the value in your hashmap, but you can't change both at the same time.

您可以更改hashmap中的键或值,但不能同时更改这两个键或值。

#15


0  

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

or

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

Integer is Primitive data types http://cs.fit.edu/~ryan/java/language/java-data.html, so you need to take it out, make some process, then put it back. if you have a value which is not Primitive data types, you only need to take it out, process it, no need to put it back into the hashmap.

Integer是原始数据类型http://cs.fit.edu/~ryan/java/language/java /java-data.html,所以需要取出它,做一些处理,然后再放回去。如果你有一个不是原始数据类型的值,你只需要取出它,处理它,不需要把它放回hashmap中。

#16


0  

Since I can't comment to a few answers due to less reputation, I will post a solution which I applied.

由于声誉不好,我无法对一些答案进行评论,所以我将发布一个我应用的解决方案。

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
   }
}