假设我们在Java中有HashMap<String, Integer>
。
如果我找到的每个字符串存在,如何更新(递增)字符串键的整数值?
可以移除并重新进入该对,但开销将是一个问题 另一种方法是刚刚放置新对,旧的对将被替换。
在后一种情况下,如果与我试图插入的新密钥存在哈希码冲突会发生什么?哈希表的正确行为是为它分配一个不同的位置,或者在当前存储桶中创建一个列表。
答案 0 :(得分:867)
map.put(key, map.get(key) + 1);
应该没问题。它将更新现有映射的值。请注意,这使用自动装箱。
答案 1 :(得分:88)
您可以使用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
等。
答案 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,否则返回当前值。
如果地图是跨线程共享的,那么我们可以使用ConcurrentHashMap
和AtomicInteger。来自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
})
])
}