[英]Java HashMap performing put() and get() in same line
I am using a HashMap<String, Integer> to keep track of count of an occurrence of a specific string.我正在使用 HashMap<String, Integer> 来跟踪特定字符串出现的次数。 I am performing this operation in a single-thread manner in the following way:
我通过以下方式以单线程方式执行此操作:
HashMap<String, Integer> count = new HashMap<>();
// List<String≥ words = ...;
for (String word : words) {
if (!count.containsKey(word)) {
count.put(word, 0);
}
count.put(word, count.get(word) + 1);
}
Is it possible, for the same word, the count increases by more than 1 because I am performing a put and get on the same key at the same time?对于同一个单词,是否有可能因为我在同一时间执行 put 和 get 操作而导致计数增加超过 1? ie Let's say the word = "hello".
即让我们说=“你好”这个词。 Initially, count.get(word) => 1. When I perform count.put(word, count.get(word) + 1), if I do count.get(word), instead of getting 2, I get 3.
最初,count.get(word) => 1。当我执行count.put(word, count.get(word) + 1) 时,如果我执行count.get(word),我得到的不是2,而是3。
To answer your questions directly: no it is not possible for the statement count.put(word, count.get(word) + 1)
to increment the value by more than 1. Although the two method calls are in the same statement they are performed sequentially: the get
is performed first to find the second argument to pass to the put
.直接回答您的问题:不,语句
count.put(word, count.get(word) + 1)
将值增加count.put(word, count.get(word) + 1)
以上。虽然这两个方法调用在同一个语句中,但它们是顺序执行:首先执行get
以找到要传递给put
的第二个参数。
You can combine your missing key test and initialisation into a single statement:您可以将缺少的密钥测试和初始化组合到一个语句中:
count.putIfAbsent(word, 0);
This conveniently returns the value afterwards, allowing:这方便地在之后返回值,允许:
count.put(word, 1 + count.putIfAbsent(word, 0));
However there is also a method that already combines those two operations:然而,还有一种方法已经结合了这两个操作:
count.merge(word, 1, Integer::sum);
Map
has methods compute
and merge
that would allow to implement shorter updates of the values for the keys: Map
具有compute
和merge
方法,可以实现键值的更短更新:
for (String word : words) {
count.compute(word, (w, prev) -> prev == null ? 1 : prev + 1);
}
for (String word : words) {
count.merge(word, 1, (prev, one) -> prev + one);
}
Lambda expression (prev, one) -> prev + one
is actually a function of two int
arguments returning their sum, therefore it may be replaced with a method reference Integer::sum
: Lambda 表达式
(prev, one) -> prev + one
实际上是两个int
参数返回它们的总和的函数,因此它可以替换为方法引用Integer::sum
:
for (String word : words) {
count.merge(word, 1, Integer::sum);
}
It absolutely safe to do it in a single thread.在单个线程中执行它绝对安全。 No, it's not possible that "count increases by more than 1 because I am performing a put and get on the same key at the same time" because two operations never can happen at the same time with single-threaded execution.
不,“计数增加超过 1 是不可能的,因为我在同一时间执行放置和获取相同的键”,因为单线程执行永远不会同时发生两个操作。
Code count.put(word, count.get(word) + 1);
代码
count.put(word, count.get(word) + 1);
will execute commands in following order:将按以下顺序执行命令:
Integer value1 = count.get(word);
int value2 = value1.intValue();
int value3 = value2 + 1;
Integer value4 = new Integer(value3);
count.put(word, value4);
By the way, your code will produce quite a lot of garbage and will be not very effective.顺便说一句,你的代码会产生相当多的垃圾并且不会很有效。
This way is more effective:这种方式更有效:
private static class CounterHolder{
int value;
}
Map<String, CounterHolder> count = new HashMap<>();
List<String> words = ...
for (String word : words) {
CounterHolder holder;
if (count.containsKey(word)) {
holder = new CounterHolder();
} else {
holder = new CounterHolder();
count.put(word, holder);
}
++holder.value;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.