Java ArrayList使用技巧 - 從第一個List中去除所有第二個List中與之重複的元素

需求:從 mAllList 中去除所有 mSubList 中與之重複的元素
測試數據:mAllList 中包含100000個無序無重複字符串,mSubList 中包含50000個無序無重複字符串
 

方法一、ArrayList中提供的removeAll方法(效率最低)

mAllList.removeAll(mSubList);

某次測試耗時:185665ms

方法二、雙重循環(比方法一效率高)

雙重循環分爲內外兩層循環,經過測試,將元素多的list放在外層循環效率更高(mSubList中的元素可能比mAllList多)(被刪除元素的列表mAllList放在外層循環和內層循環的實現方式有些差別),這裏的測試數據是mAllList中的元素多,實現如下:

int maxSize = mAllList.size();
for (int i = maxSize-1; i >=0; i--) {
    int size = mSubList.size();
    while (size > 0) {
        String s = mSubList.get(size-1);
        if (s.equals(mAllList.get(i))) {
            mSubList.remove(size-1);
            mAllList.remove(i);
            break;
        }
        size--;
    }
}

某次測試耗時:101510ms

方法三、利用HashMap(效率最高)

//第一步:構建mAllList的HashMap
//將mAllList中的元素作爲鍵,如果不是String類,需要實現hashCode和equals方法
//將mAllList中的元素對應的位置作爲值
Map<String, Integer> map = new HashMap<>();
for (int i = 0; i < mAllList.size(); i++) {
    map.put(mAllList.get(i), i);
}
//第二步:利用map遍歷mSubList,查找重複元素
//把mAllList中所有查到的重複元素的位置置空
for (int i = 0; i < mSubList.size(); i++) {
    Integer pos = map.get(mSubList.get(i));
    if (pos==null) {
        continue;
    }
    mAllList.set(pos, null);
}
//第三步:把mAllList中所有的空元素移除
for (int i = mAllList.size()-1; i>=0; i--) {
    if (mAllList.get(i)==null) {
        mAllList.remove(i);
    }
}

某次測試耗時:712ms

方法三的一些說明

  1. 方法三中初始化HashMap的時候已經知道了容量大小,理論上直接指定HashMap的大小避免擴容可以提高效率,但是測試發現並沒有提高,100000條數據都是幾十毫秒
  2. 雖然方法三中HashMap存的值是整數,但是不要使用int pos = map.get(mSubList.get(i));取值,會崩潰
  3. 第二步中,使用Integer pos = map.get(mSubList.get(i));取值,然後判斷 pos 是否是空來判斷map中是否包含鍵是mSubList.get(i)的值,比用map.containsKey(key)來判斷然後get取值少訪問一次哈希表
  4. 第三步中,從mAllList尾部開始遍歷移除
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章