一些测试结果
对于这个问题,我已经得到了很多很好的答案-谢谢大家-所以我决定进行一些测试,找出哪种方法实际上最快。我测试的五种方法是:
- 我在问题中介绍的“ ContainsKey”方法
- Aleksandar Dimitrov建议的“ TestForNull”方法
- Hank Gay建议的“ AtomicLong”方法
- jrudolph建议的“推动”方法
- phax.myopenid.com建议的“ MutableInt”方法
方法
这是我做的...
- 创建了五个相同的类,除了以下所示的区别。每个班级都必须执行我所介绍的场景的典型操作:打开一个10MB的文件并读入它,然后对文件中所有单词标记的频率进行计数。由于平均只花了3秒钟,所以我让它执行了10次频率计数(而不是I / O)。
- 定时10次迭代的循环而不是I / O操作的时间,并基本上使用Java Cookbook中的Ian Darwin的方法记录所花费的总时间(以时钟秒为单位)。
- 依次执行了所有五个测试,然后又进行了三次。
- 平均每种方法的四个结果。
结果
我将首先提供结果,并为感兴趣的人提供以下代码。
如所预期的,ContainsKey方法是最慢的,因此,与该方法的速度相比,我将给出每种方法的速度。
- ContainsKey: 30.654秒(基准)
- AtomicLong: 29.780秒(速度的1.03倍)
- TestForNull: 28.804秒(速度的1.06倍)
- 宝座: 26.313秒(1.16倍的速度)
- MutableInt: 25.747秒(1.19倍的速度)
结论
似乎只有MutableInt方法和Trove方法要快得多,因为它们的性能提升超过10%。但是,如果线程成为问题,AtomicLong可能比其他线程更具吸引力(我不确定)。我也用final
变量运行了TestForNull ,但是差别可以忽略不计。
请注意,我没有介绍不同情况下的内存使用情况。我很高兴听到任何对MutableInt和Trove方法将如何影响内存使用有深刻见解的人。
我个人认为MutableInt方法最吸引人,因为它不需要加载任何第三方类。因此,除非我发现问题,否则这是我最有可能采取的方法。
编码
这是每种方法的关键代码。
ContainsKey
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
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);
}
原子长
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();
宝库
import gnu.trove.TObjectIntHashMap;
...
TObjectIntHashMap<String> freq = new TObjectIntHashMap<String>();
...
freq.adjustOrPutValue(word, 1, 1);
MutableInt
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();
}