黑馬程序員_java高效計數器

------- 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。

------- android培訓java培訓、期待與您交流! ----------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章