-------
android培訓、java培訓、期待與您交流! ----------
你可能經常使用HashMap作爲一個計數器來理解頻率的東西從數據庫或文本。本文比較了3種不同的方法來實現計數器使用HashMap。
1、傳統的計數器
如果你使用這樣一個計數器,你的代碼可能看起來像下面的:
String s = "one two three two three three";
String[] sArr = s.split(" ");
//naive approach
HashMap<String, Integer> counter = new HashMap<String, Integer>();
for (String a : sArr) {
if (counter.containsKey(a)) {
int oldValue = counter.get(a);
counter.put(a, oldValue + 1);
} else {
counter.put(a, 1);
}
}
在每個循環,你檢查是否存在與否的關鍵。如果是,增加舊值1,如果不是,將它設置爲1。該方法簡單、直觀,但它不是最有效的方法。這種方法被認爲是低效率的原因如下:
>>containsKey(),get()被稱爲兩次當一個鍵已經存在。這意味着搜索地圖兩次。
>>因爲整數是不可變的,每個循環將創建一個新的一個增量的舊值
2、更好的計數器
我們想要一個可變的整數自然避免創建許多整數對象。一個可變的整數類定義如下:
這似乎是更好的,因爲它不需要創建許多整數對象了。然而,搜索仍是兩次在每個循環如果一個關鍵的存在。class MutableInteger {
private int val;
public MutableInteger(int val) {
this.val = val;
}
public int get() {
return val;
}
public void set(int val) {
this.val = val;
}
//used to print value convinently
public String toString(){
return Integer.toString(val);
}
}
和計數器是改善和改變如下:
HashMap<String, MutableInteger> newCounter = new HashMap<String, MutableInteger>();
for (String a : sArr) {
if (newCounter.containsKey(a)) {
MutableInteger oldValue = newCounter.get(a);
oldValue.set(oldValue.get() + 1);
} else {
newCounter.put(a, new MutableInteger(1));
}
}
3、高效的計數器
這個HashMap。把(key,value)方法返回當前的價值的關鍵。這是有用的,因爲我們可以使用參考舊的值來更新值沒有搜索一個更多的時間!
HashMap<String, MutableInteger> efficientCounter = new HashMap<String, MutableInteger>();
for (String a : sArr) {
MutableInteger initValue = new MutableInteger(1);
MutableInteger oldValue = efficientCounter.put(a, initValue);
if(oldValue != null){
initValue.set(oldValue.get() + 1);
}
}
4、性能差異
測試性能的三種不同的方法,使用以下代碼。性能測試是在100萬次。原始的結果如下:
Naive Approach : 222796000
Better Approach: 117283000
Efficient Approach: 96374000
不同的是重要的- 223與117和96。有很多區別,比較幼稚,這表明創建對象是昂貴的!
String s = "one two three two three three";
String[] sArr = s.split(" ");
long startTime = 0;
long endTime = 0;
long duration = 0;
// naive approach
startTime = System.nanoTime();
HashMap<String, Integer> counter = new HashMap<String, Integer>();
for (int i = 0; i < 1000000; i++)
for (String a : sArr) {
if (counter.containsKey(a)) {
int oldValue = counter.get(a);
counter.put(a, oldValue + 1);
} else {
counter.put(a, 1);
}
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("Naive Approach : " + duration);
// better approach
startTime = System.nanoTime();
HashMap<String, MutableInteger> newCounter = new HashMap<String, MutableInteger>();
for (int i = 0; i < 1000000; i++)
for (String a : sArr) {
if (newCounter.containsKey(a)) {
MutableInteger oldValue = newCounter.get(a);
oldValue.set(oldValue.get() + 1);
} else {
newCounter.put(a, new MutableInteger(1));
}
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("Better Approach: " + duration);
// efficient approach
startTime = System.nanoTime();
HashMap<String, MutableInteger> efficientCounter = new HashMap<String, MutableInteger>();
for (int i = 0; i < 1000000; i++)
for (String a : sArr) {
MutableInteger initValue = new MutableInteger(1);
MutableInteger oldValue = efficientCounter.put(a, initValue);
if (oldValue != null) {
initValue.set(oldValue.get() + 1);
}
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("Efficient Approach: " + duration);
當你使用一個計數器,你可能還需要一個函數來進行地圖的價值。你可以查看常用方法的HashMap。