首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Java中增加Map值的最有效方法是什么?

在Java中增加Map值的最有效方法是什么?
EN

Stack Overflow用户
提问于 2018-10-16 05:35:24
回答 2查看 0关注 0票数 0

我希望这个问题对于这个论坛来说不算太基础,但我们会看到。我想知道如何重构一些代码以获得更好的性能,这些代码运行了很多次。

假设我正在使用Map(可能是HashMap)创建一个单词频率列表,其中每个键都是一个字符串,其中包含要计数的单词,并且值是一个Integer,每次找到单词的标记时它都会递增。

在Perl中,增加这样的值将非常简单:

代码语言:javascript
复制
$map{$word}++;

但在Java中,它要复杂得多。这是我目前正在做的方式:

代码语言:javascript
复制
int count = map.containsKey(word) ? map.get(word) : 0;
map.put(word, count + 1);

当然,这取决于较新Java版本中的自动装箱功能。我想知道你是否可以建议一种更有效的方法来增加这样的价值。是否有良好的性能原因可以避开Collections框架并使用其他东西?

EN

回答 2

Stack Overflow用户

发布于 2018-10-16 13:58:33

查看Google Collections Library这样的事情总是一个好主意。在这种情况下,Multiset可以解决这个问题:

代码语言:javascript
复制
Multiset bag = Multisets.newHashMultiset();
String word = "foo";
bag.add(word);
bag.add(word);
System.out.println(bag.count(word)); // Prints 2

有类似Map的方法来迭代键/条目等。在内部,实现当前使用a HashMap<E, AtomicInteger>,所以你不会招致拳击费用。

票数 0
EN

Stack Overflow用户

发布于 2018-10-16 14:49:04

一些测试结果

我已经为这个问题得到了很多好的答案 - 谢谢大家 - 所以我决定运行一些测试并找出哪种方法实际上最快。我测试的五种方法是:

  • 我在问题中提出的“ContainsKey”方法
  • Aleksandar Dimitrov建议的“TestForNull”方法
  • Hank Gay建议的“AtomicLong”方法
  • jrudolph建议的“Trove”方法
  • phax.myopenid.com建议的“MutableInt”方法

方法

这就是我做的......

  1. 创建了五个相同的类,除了下面显示的差异。每个类都必须执行我演示的场景的典型操作:打开10MB文件并读入,然后执行文件中所有单词令牌的频率计数。由于这平均只花了3秒钟,我让它执行频率计数(不是I / O)10次。
  2. 定时循环10次迭代而不是I / O操作,并记录了基本上使用Java Cookbook中的Ian Darwin方法所花费的总时间(以秒为单位)。
  3. 连续进行了所有五项测试,然后又进行了三次测试。
  4. 平均每种方法的四个结果。

结果

我将首先介绍结果,并为感兴趣的人提供下面的代码。

的containsKey方法是,如预期,最慢的,所以我给每个方法的速度相比,该方法的速度。

  • ContainsKey: 30.654秒(基线)
  • AtomicLong: 29.780秒(快1.03倍)
  • TestForNull: 28.804秒(快1.06倍)
  • Trove: 26.313秒(快了1.16倍)
  • MutableInt: 25.747秒(快了1.19倍)

结论

似乎只有MutableInt方法和Trove方法明显更快,因为只有它们的性能提升超过10%。但是,如果线程是一个问题,AtomicLong可能比其他人更有吸引力(我不太确定)。我还使用final变量运行TestForNull ,但差异可以忽略不计。

请注意,我没有在不同的方案中分析内存使用情况。我很高兴听到任何人对MutableInt和Trove方法如何影响内存使用情况有很好的见解。

就个人而言,我发现MutableInt方法最具吸引力,因为它不需要加载任何第三方类。所以,除非我发现它的问题,这是我最有可能的方式。

代码

以下是每种方法的关键代码。

的containsKey

代码语言:javascript
复制
import java.util.HashMap;
import java.util.Map;
...
Map<String, Integer> freq = new HashMap<String, Integer>();
...
int count = freq.containsKey(word) ? freq.get(word) : 0;
freq.put(word, count + 1);

TestForNull

代码语言:javascript
复制
import java.util.HashMap;
import java.util.Map;
...
Map<String, Integer> freq = new HashMap<String, Integer>();
...
Integer count = freq.get(word);
if (count == null) {
    freq.put(word, 1);
}
else {
    freq.put(word, count + 1);
}

的AtomicLong

代码语言:javascript
复制
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
...
final ConcurrentMap<String, AtomicLong> map = 
    new ConcurrentHashMap<String, AtomicLong>();
...
map.putIfAbsent(word, new AtomicLong(0));
map.get(word).incrementAndGet();

特罗韦

代码语言:javascript
复制
import gnu.trove.TObjectIntHashMap;
...
TObjectIntHashMap<String> freq = new TObjectIntHashMap<String>();
...
freq.adjustOrPutValue(word, 1, 1);

MutableInt

代码语言:javascript
复制
import java.util.HashMap;
import java.util.Map;
...
class MutableInt {
  int value = 1; // note that we start at 1 since we're counting
  public void increment () { ++value;      }
  public int  get ()       { return value; }
}
...
Map<String, MutableInt> freq = new HashMap<String, MutableInt>();
...
MutableInt count = freq.get(word);
if (count == null) {
    freq.put(word, new MutableInt());
}
else {
    count.increment();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100002914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档