我有一个包含7.6M行的文件。每行的格式如下:A,B,C,D其中B,C,D是用于计算A的重要性级别的值,它是每行唯一的字符串标识符。我的方法是:Java HashMap vs hashset性能
private void read(String filename) throws Throwable {
BufferedReader br = new BufferedReader(new FileReader(filename));
Map<String, Double> mmap = new HashMap<>(10000000,0.8f);
String line;
long t0 = System.currentTimeMillis();
while ((line = br.readLine()) != null) {
split(line);
mmap.put(splitted[0], 0.0);
}
long t1 = System.currentTimeMillis();
br.close();
System.out.println("Completed in " + (t1 - t0)/1000.0 + " seconds");
}
private void split(String line) {
int idxComma, idxToken = 0, fromIndex = 0;
while ((idxComma = line.indexOf(delimiter, fromIndex)) != -1) {
splitted[idxToken++] = line.substring(fromIndex, idxComma);
fromIndex = idxComma + 1;
}
splitted[idxToken] = line.substring(fromIndex);
}
其中虚拟值0.0被插入用于“分析”目的,并且splitted是为该类定义的简单字符串数组。我最初使用String的split()方法,但发现上述速度更快。
当我运行上面的代码时,需要12秒来解析比我认为应该花费更多的文件。如果我,例如,用一个Vector的字符串替换HashMap,并从每一行取第一个条目(即我没有放置一个相关的值,因为这应该是分期不变的),整个文件可以在小于3秒。 (我曾试图通过预先分配大小和相应地设置负载因数来最大限度地减少调整大小的次数),或者(ii)hashCode()和HashMap中的大量碰撞功能有点慢。我怀疑它(ii),因为如果我使用HashSet,可以在4秒内读取文件。
我的问题是:什么可能是HashMap执行如此缓慢的原因?对于这个尺寸的地图,hashCode()是不够的,还是有一些基本的东西我忽略了?
尝试用一些静态常量最终取代你的'0.0'虚值。 '0.0'被替换为'Double.valueOf',每次创建一个新对象。而在HashSet中,只有一个预分配的虚拟对象被使用。我不确定这是什么原因,但它可以是 – esin88
'splitted []'的最后一个元素将始终保存整行。这不是你想要的。 – EJP
'HashSet'由内部的'HashMap'支持,所以唯一的区别就是你的虚拟'0.0'的自动装箱。 – bashnesnos