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

时间:2010-11-11 18:34:01

标签: java key hashmap

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

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

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

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

17 个答案:

答案 0 :(得分:867)

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

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

答案 1 :(得分:88)

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等。

答案 2 :(得分:49)

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

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

答案 3 :(得分:31)

简化的 Java 8 方式:

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

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

核心Java支持这一点:HashMap<K,V> getOrDefault(Object key, V defaultValue)

答案 4 :(得分:27)

Integer替换为AtomicInteger,并在其上调用其中一种incrementAndGet / getAndIncrement方法。

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

答案 5 :(得分:17)

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

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

但是,更快的解决方案(提供线程安全性不是问题)是使用TObjectIntHashMap提供增量(键)方法并使用原语和更少的对象而不是创建AtomicIntegers。 e.g。

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

答案 6 :(得分:16)

一线解决方案:

<script>

    $(document).ready(function () {

        $('#content').scrollPagination({
            nop: 10, // The number of posts per scroll to be loaded
            offset: 0, // Initial offset, begins at 0 in this case
            error: 'No More Posts!', // When the user reaches the end this is the message that is
            // displayed. You can change this if you want.
            delay: 500, // When you scroll down the posts will load after a delayed amount of time.
            // This is mainly for usability concerns. You can alter this as you see fit
            scroll: true // The main bit, if set to false posts will not load as the user scrolls. 
                    // but will still load if the user clicks.

        });

    });

</script>

答案 7 :(得分:11)

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

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

答案 8 :(得分:9)

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

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

答案 9 :(得分:6)

可能会有点迟,但这是我的两分钱。

如果您使用的是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,否则返回当前值。

如果地图是跨线程共享的,那么我们可以使用ConcurrentHashMapAtomicInteger。来自doc:

  

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来获取密钥B的值,然后在其值incrementAndGet()上调用AtomicInteger。我们可以优化它,方法putIfAbsent返回密钥的值(如果已存在):

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

另一方面,如果我们计划使用AtomicLong,那么根据高争用的文档,LongAdder的预期吞吐量会显着提高,但会占用更高的空间消耗。另请查看question

答案 10 :(得分:5)

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

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

答案 11 :(得分:2)

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

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

答案 13 :(得分:1)

由于声誉较低,我无法评论几个答案,因此我会发布一个我申请的解决方案。

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

答案 14 :(得分:0)

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

Integer是原始数据类型http://cs.fit.edu/~ryan/java/language/java-data.html,因此您需要将其取出,进行一些处理,然后再将其放回原处。如果你有一个不是原始数据类型的值,你只需要把它拿出来,处理它,不需要把它放回到hashmap中。

答案 15 :(得分:0)

尝试:

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

答案 16 :(得分:0)

使用内置的功能'computeIfPresent'的Java8

示例:

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ],
      },
      {
        test: /\.scss$/,
        use: [
          'vue-style-loader',
          'css-loader',
          'sass-loader'
        ],
      },
      {
        test: /\.sass$/,
        use: [
          'vue-style-loader',
          'css-loader',
          'sass-loader?indentedSyntax'
        ],
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
            // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
            // the "scss" and "sass" values for the lang attribute to the right configs here.
            // other preprocessors should work out of the box, no loader config like this necessary.
            'scss': [
              'vue-style-loader',
              'css-loader',
              'sass-loader'
            ],
            'sass': [
              'vue-style-loader',
              'css-loader',
              'sass-loader?indentedSyntax'
            ]
          }
          // other vue-loader options go here
        }
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    },
    extensions: ['*', '.js', '.vue', '.json']
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true,
    overlay: true
  },
  performance: {
    hints: false
  },
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  // http://vue-loader.vuejs.org/en/workflow/production.html
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ])
}