首页 文章

给定java hashmap中的键,如何更新值?

提问于
浏览
511

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

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

人们可以移除并重新进入该对,但开销将是一个问题 .
另一种方法是刚刚放置新的一对,旧的一对将被替换 .

在后一种情况下,如果与我试图插入的新密钥存在哈希码冲突会发生什么?哈希表的正确行为是为其分配不同的位置,或者在当前存储桶中创建一个列表 .

16 回答

  • 1

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

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

  • 14

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

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

    可能会有点晚,但这是我的两分钱 .

    如果您使用的是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),则此方法将其与给定值相关联并返回null,否则返回当前值 .

    如果 Map 是跨线程共享的,那么我们可以使用 ConcurrentHashMapAtomicInteger . 从文档:

    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]
    

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

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

    另外,如果我们计划使用AtomicLong,那么根据高争用的文档,LongAdder的预期吞吐量要高得多,这是以更高的空间消耗为代价的 . 另请检查question .

  • 2

    这里有一个误导性的答案,暗示如果密钥存在,Hashtable put方法将替换现有值,对于Hashtable而言,这不适用于HashMap . 请参阅Javadoc for HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29

  • 1

    一线解决方案:

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

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

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

  • 5

    哈希是否存在(0为值)还是在第一个增量上“放”到 Map 上?如果它是第一个增量“put”,代码应如下所示:

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

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

  • 26
    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,因此您需要将其取出,进行一些处理,然后将其放回原处 . 如果你有一个不是原始数据类型的值,你只需要把它拿出来,处理它,不需要把它放回到hashmap中 .

  • 45

    使用 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 ....
    
    }
    
  • 8

    尝试:

    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中的键或值,但不能同时更改它们 .

  • 74

    简化的 Java 8 方式:

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

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

    这在核心Java中得到支持:HashMap<K,V> getOrDefault(Object key, V defaultValue)

  • 799

    您可以像下面一样增加,但是您需要检查是否存在,以便不抛出NullPointerException

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

    由于声誉较低,我无法评论几个答案,因此我将发布一个我应用的解决方案 .

    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
       }
    }
    
  • 24
    hashmap.put(key, hashmap.get(key) + 1);
    

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

  • 0

    @ Matthew的解决方案是最简单的,并且在大多数情况下表现都很好 .

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

    但是,更快的解决方案(提供线程安全性不是问题)是使用TObjectIntHashMap,它提供增量(键)方法并使用基元和少于创建AtomicIntegers的对象 . 例如

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

相关问题