如何更新一个值,给定一个哈希图中的键?

假设我们在Java中有一个HashMap<String, Integer>

我如何更新(增量)string-key的整数值为每个存在的字符串我找到?

可以删除并重新输入货币对,但开销会是一个问题。
另一种方法是只放新的一对,旧的会被替换。

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

1191810 次浏览

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

另一种选择是将int包装在您自己的MutableInteger类中,该类具有increment()方法,您只有一个线程安全问题需要解决。

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

应该没问题。它将更新现有映射的值。请注意,这使用了自动装箱。在map.get(key)的帮助下,我们获得了相应键的值,然后您可以根据您的要求进行更新。这里我更新为将值增加1。

@Matthew的解决方案是最简单的,在大多数情况下都能很好地执行。

如果您需要高性能,则原子整数是一个更好的解决方案ala@BalusC。

然而,更快的解决方案(前提是线程安全不是问题)是使用TObjectIntHashMap任务列表,它提供了一个增量(键)方法,并使用原语和比创建原子整数更少的对象。

TObjectIntHashMap<String> map = new TObjectIntHashMap<String>()
map.increment("aaa");
hashmap.put(key, hashmap.get(key) + 1);

方法put取代现有键的值,如果不存在,将创建它。

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


}

尝试:

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中的键或值,但不能同时更改两者。

您可以像下面这样递增,但您需要检查是否存在,以便不抛出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);
}

这里这个问题有误导性的答案,这意味着如果键存在,Hashtable put方法将替换现有值,这对Hashtable来说不是真的,而是对HashMap来说。参见Javadoc for HashMaphttp://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K%20V%29

Java8路:

您可以使用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);

此外,还有很多其他有用的方法,例如putIfAbsentgetOrDefaultforEach等。

可能有点晚了,但这是我的两分钱。

如果您使用的是Java8,那么您可以使用电脑到账方法。如果指定键的值存在且非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]

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

如果映射跨线程共享,那么我们可以使用ConcurrentHashMap原子整数。来自文档:

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

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

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]

顺便说一下,如果我们计划使用原子长度,那么根据高争用下的留档,LongAdder的预期吞吐量显着更高,而牺牲了更高的空间消耗。还要检查这个问题

简化的Java8方式:

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

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

这在核心Java中得到支持:HashMapgetOrDefault(Object key, V defaultValue)#默认值

单线解决方案:

map.put(key, map.containsKey(key) ? map.get(key) + 1 : 1);
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);

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

由于声誉较差,我无法对几个答案发表评论,我将发布我应用的解决方案。

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

没有NullPointerException的更干净的解决方案是:

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

使用Java8内置函数'computeIfPresent'

示例:

public class ExampleToUpdateMapValue {


public static void main(String[] args) {
Map<String,String> bookAuthors = new TreeMap<>();
bookAuthors.put("Genesis","Moses");
bookAuthors.put("Joshua","Joshua");
bookAuthors.put("Judges","Samuel");


System.out.println("---------------------Before----------------------");
bookAuthors.entrySet().stream().forEach(System.out::println);
// To update the existing value using Java 8
bookAuthors.computeIfPresent("Judges", (k,v) -> v = "Samuel/Nathan/Gad");


System.out.println("---------------------After----------------------");
bookAuthors.entrySet().stream().forEach(System.out::println);
}
}