如何更新一个值,给定一个java hashmap中的键?
假设我们在Java中有一个HashMap<String, Integer>
。
如何更新(增量)string的整数值为每个存在的string我find?
人们可以删除并重新进场,但是开销会是一个问题。
另一种方法是把新的一对,旧的将被replace。
在后一种情况下,如果发生与我试图插入的新密钥相冲突的情况,会发生什么? 哈希表的正确行为是为它指定一个不同的地方,或者在当前的存储桶中创build一个列表。
map.put(key, map.get(key) + 1);
应该没事。 它将更新现有映射的值。 请注意,这使用自动装箱。
hashmap.put(key, hashmap.get(key) + 1);
put
方法将取代现有密钥的值,如果不存在,将会创build它。
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
等。
用AtomicInteger
replaceInteger
,然后调用其中的一个incrementAndGet
/ getAndIncrement
方法。
另一种方法是在你自己的MutableInteger
类中包含一个int
,该类有一个increment()
方法,但你只有一个线程安全问题需要解决。
@马修的解决scheme是最简单的,并且在大多数情况下都会performance出色。
如果您需要高性能,AtomicInteger是更好的解决schemeala @BalusC。
然而,更快的解决scheme(提供线程安全性不是问题)是使用TObjectIntHashMap ,它提供了一个增量(键)方法,并使用基元和less于创buildAtomicIntegers的对象。 例如
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); }
一行解决scheme:
map.put(key, map.containsKey(key) ? map.get(key) + 1 : 1);
简化的Java 8方式:
map.put(key, map.getOrDefault(key, 0) + 1);
这使用HashMap的方法来检索一个键的值,但是如果键不能被检索,它将返回指定的默认值(在这个例子中是'0')。
核心Java支持以下内容: HashMap <K,V> getOrDefault(Object key,V defaultValue)
哈希是否存在(以0作为值)还是在第一个增量中“放”到地图? 如果它是“放”在第一个增量,代码应该是这样的:
if (hashmap.containsKey(key)) { hashmap.put(key, hashmap.get(key)+1); } else { hashmap.put(key,1); }
可能有点晚,但这是我的两分钱。
如果您正在使用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]
我们也可以利用另一种方法putIfAbsent来放置一个键。 如果指定的键还没有与一个值相关联(或被映射为null),则此方法将其与给定值关联,并返回null,否则返回当前值。
如果地图在线程中共享,那么我们可以使用ConcurrentHashMap
和AtomicInteger 。 从文档:
AtomicInteger
是一个可以自动更新的int值。 AtomicInteger用于primefaces递增计数器等应用程序,不能用作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]
需要注意的一点是我们调用get
来得到关键字B
的值,然后调用incrementAndGet()
的值,当然这个值是AtomicInteger
。 我们可以优化它,因为putIfAbsent
方法在已经存在的情况下返回键的值:
map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]
在附注中,如果我们打算使用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
尝试:
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);
整数是原始数据typeshttp://cs.fit.edu/~ryan/java/language/java-data.html ,所以你需要把它拿出来,做一些过程,然后把它放回去。 如果你有一个不是Primitive数据types的值,你只需要把它拿出来处理它,不需要把它放回hashmap。
由于缺乏口碑,我不能评论几个答案,所以我会发布一个我申请的解决scheme。
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 } }