lae*_*tis 585 java key hashmap
假设我们有一个HashMap<String, Integer>Java.
对于我找到的每个字符串的存在,如何更新(递增)字符串键的整数值?
人们可以移除并重新进入该对,但开销将是一个问题.
另一种方法是刚刚放置新的一对,旧的一对将被替换.
在后一种情况下,如果与我试图插入的新密钥存在哈希码冲突会发生什么?哈希表的正确行为是为其分配不同的位置,或者在当前存储桶中创建一个列表.
Mat*_*hen 913
map.put(key, map.get(key) + 1);
Run Code Online (Sandbox Code Playgroud)
应该没事.它将更新现有映射的值.请注意,这使用自动装箱.
dam*_*uar 101
您可以使用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"));
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用merge方法,其中1是默认值,函数将现有值增加1:
words.merge("hello", 1, Integer::sum);
Run Code Online (Sandbox Code Playgroud)
此外,有一堆其他有用的方法,例如putIfAbsent,getOrDefault,forEach等.
ora*_*uiz 48
hashmap.put(key, hashmap.get(key) + 1);
Run Code Online (Sandbox Code Playgroud)
该方法put将替换现有密钥的值,如果不存在则将创建它.
Chr*_*ull 42
简化的Java 8方式:
map.put(key, map.getOrDefault(key, 0) + 1);
Run Code Online (Sandbox Code Playgroud)
这使用HashMap的方法来检索键的值,但是如果无法检索键,则返回指定的默认值(在本例中为"0").
这在核心Java中得到支持:HashMap <K,V> getOrDefault(Object key,V defaultValue)
Bal*_*usC 28
更换Integer的AtomicInteger并调用的一个incrementAndGet/ getAndIncrement它的方法.
另一种方法是int在你自己的MutableInteger类中包含一个有increment()方法的类,你只需解决一个安全问题.
Pet*_*rey 17
@ Matthew的解决方案是最简单的,并且在大多数情况下表现都很好.
如果您需要高性能,AtomicInteger是一个更好的解决方案ala @BalusC.
但是,更快的解决方案(提供线程安全性不是问题)是使用TObjectIntHashMap,它提供增量(键)方法并使用原语和少于创建AtomicIntegers的对象.例如
TObjectIntHashMap<String> map = new TObjectIntHashMap<String>()
map.increment("aaa");
Run Code Online (Sandbox Code Playgroud)
小智 16
一线解决方案:
map.put(key, map.containsKey(key) ? map.get(key) + 1 : 1);
Run Code Online (Sandbox Code Playgroud)
isu*_*uru 13
您可以像下面一样增加,但是您需要检查是否存在,以便不抛出NullPointerException
if(!map.containsKey(key)) {
p.put(key,1);
}
else {
p.put(key, map.getKey()+1);
}
Run Code Online (Sandbox Code Playgroud)
小智 9
哈希是否存在(0为值)还是在第一个增量上"放"到地图上?如果它是第一个增量"put",代码应如下所示:
if (hashmap.containsKey(key)) {
hashmap.put(key, hashmap.get(key)+1);
} else {
hashmap.put(key,1);
}
Run Code Online (Sandbox Code Playgroud)
可能会有点晚,但这是我的两分钱.
如果您使用的是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]
Run Code Online (Sandbox Code Playgroud)
我们还可以使用另一个方法putIfAbsent来放一个键.如果指定的键尚未与值关联(或映射为null),则此方法将其与给定值相关联并返回null,否则返回当前值.
如果地图是跨线程共享的,那么我们可以使用ConcurrentHashMap和AtomicInteger.来自doc:
An
AtomicInteger是一个可以原子方式更新的int值.AtomicInteger用于诸如原子递增计数器的应用程序中,不能用作Integer的替代.但是,此类确实扩展了Number,以允许通过处理基于数字的类的工具和实用程序进行统一访问.
我们可以使用它们如图所示:
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]
Run Code Online (Sandbox Code Playgroud)
需要注意的一点是,我们正在调用get获取key的值B,然后调用incrementAndGet()其值,这当然是AtomicInteger.我们可以优化它,因为方法putIfAbsent返回密钥的值(如果已经存在):
map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]
Run Code Online (Sandbox Code Playgroud)
另外,如果我们计划使用AtomicLong,那么根据高争用的文档,LongAdder的预期吞吐量会显着提高,但会占用更高的空间消耗.还要检查这个问题.
小智 5
由于声誉较低,我无法对一些答案发表评论,因此我将发布我应用的解决方案。
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
}
}
Run Code Online (Sandbox Code Playgroud)
没有NullPointerException的更干净的解决方案是:
map.replace(key, map.get(key) + 1);
Run Code Online (Sandbox Code Playgroud)