我有一個包含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