優化map查找操作

例子:我們經常會碰到統計一個文檔中的字符串出現的次數這樣的問題,在這樣的問題中會創建一個這樣的map來存放數據:

Map<String, Integer>map = new HashMap<String, Integer>();

那麼對於下一個字符串String x=”abc”;
一般情況下要做的操作爲:

int count = map.containsKey(x)?map.get(x):0;
map.put(x, count++);

首先查看map中是否已經包含該字符串,再獲得該字符串對應的value值,其實根據java api的get()方法,可以省略containsKey()操作,get()方法在map中:

  1. 包含該key值時,返回對應的value值;
  2. 不包含該key值時,返回null對象。

故上述操作可以改成:

Integer count = map.get(x);
        if(count == null)
            map.put(x, 1);
        else
            map.put(x, ++count);

這樣就省去了一次查找map的過程。


最壞進行兩次map操作,並使用MutableInteger 代替Integer類型對象
但是這樣的代碼在每次更新key值對應的value值時,會創建新的Integer對象來代替原無效的Integer對象,這樣就會導致原無效Integer對象需要等待一個GC週期,並在下一個週期被回收。但是Integer爲 immutable類型,那麼是否可以使用一個MutableInteger如下,來代替Integer類型的value對象呢?

public 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;
      }
    }

用該MutableInteger 對象代替Integer類型的value值,故有如下代碼操作:

public void incrementCount(String key){
        MutableInteger count = map.get(key);
        if(null == count){
            map.put(key, new MutableInteger(1));
        }else
            count.set(count.get()+1);
    }

那麼,在最壞情況下(String字符串爲第一次出現),需要兩次map操作:get(),和put()操作。
並且在每次更新value值時,不需要反覆創建Integer值,並將無效原value值等待GC回收。而是獲得map中key值對應的value的可變對象MutableInteger的引用,然後更新堆內存上的value對象中的成員變量。


只是用一次map操作,就可以更新value值:
查看java api會發現其中的put()方法:

  1. 若key值存在,則返回對應的value值,
  2. 否則,返回null對象。

那麼,是否可以使用MutableInteger來將map中更新value的操作減少到一次呢?
如下代碼:

    public void incrementCount(String key){
        MutableInteger tmpCount = new MutableInteger(1);
        MutableInteger oldCount = map.put(key, tmpCount);
        if(null != oldCount)
            tmpCount.set(oldCount.get()+1);
    }

在這個實現中,配合MutableInteger類型對象的使用(基於java的引用傳遞)可以將map中value的更新操作減少到一次,但是也有一個無效對象需要等待GC回收的問題。
可以說這種方法是基於空間換時間。而上述第二種方法是時間換空間。


參考文獻:
1,Most efficient way to increment a Map value in Java — Only search the key once

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