最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中ArrayList的removeAll方法詳解

 更新時間:2017年07月04日 09:13:21   作者:李國旺  
這篇文章主要給大家介紹了關于Java中ArrayList的removeAll方法的相關資料,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友們下面跟著小編一起來看看吧。

本文介紹的是關于Java中ArrayList的removeAll方法的相關內容,分享出來供大家參考學習,下面來一起看看詳細的介紹:

在開發(fā)過程中,遇到一個情況,就是從所有騎手Id中過濾沒有標簽的騎手Id(直接查詢沒有標簽的騎手不容易實現(xiàn)),

List<Integer> allRiderIdList = new ArrayList(); // 所有的騎手,大致有23W數(shù)據(jù)
List<Integer> hasAnyTagRiderId = new ArrayList(); // 有標簽的騎手, 大致有21W數(shù)據(jù)
List<Integer> withoutAnyTagRiderList = allRiderIdList.removeAll(hasAnyTagRiderId);

邏輯很簡單,就是取一個差集,這樣子就拿到?jīng)]有任何標簽的騎手數(shù)據(jù)。

但是在實際開發(fā)過程中,removeAll這個動作很耗時,做測試大概要4分鐘左右。查看ArrayList中removeAll的源碼片段:

public boolean removeAll(Collection<?> c) {
 Objects.requireNonNull(c);
 return batchRemove(c, false);
}

private boolean batchRemove(Collection<?> c, boolean complement) {
 final Object[] elementData = this.elementData;
 int r = 0, w = 0;
 boolean modified = false;
 try {
 for (; r < size; r++) // 循環(huán)原來的list
  if (c.contains(elementData[r]) complement) // 這里調用contains方法
  elementData[w++] = elementData[r];
 } finally {
 ....
 }
 return modified;
}

在循環(huán)過程中調用contains方法做比較,查一下ArrayList的contains方法,源代碼片段如下:

public boolean contains(Object o) {
 return indexOf(o) >= 0;
}

public int indexOf(Object o) {
 if (o null) {
 for (int i = 0; i < size; i++)
  if (elementData[i]==null)
  return i;
 } else {
 for (int i = 0; i < size; i++)
  if (o.equals(elementData[i]))
  return i;
 }
 return -1;
}

這可以看出來,在比較的過程中,又調用了一次循環(huán)。

所以removeAll兩層for循環(huán),復雜度O(m*n),所以在操作比較大的ArrayList時,這種方法是絕對不可取的。

下面看一下最終的實現(xiàn)方式:

private List<Integer> removeAll(List<Integer> src, List<Integer> target) {
 LinkedList<Integer> result = new LinkedList<>(src); //大集合用linkedlist
 HashSet<Integer> targetHash = new HashSet<>(target); //小集合用hashset
 Iterator<Integer> iter = result.iterator(); //采用Iterator迭代器進行數(shù)據(jù)的操作

 while(iter.hasNext()){ 
 if(targetHash.contains(iter.next())){
  iter.remove();
 }
 }
 return result;
}

同樣數(shù)量級list, 整個過程只需要幾十毫秒,簡直天壤之別。

回過頭來,比較一下兩種實現(xiàn)方式,為什么差距這個大。

1、外層循環(huán)

     一個是普通的for循環(huán),一個迭代器遍歷元素,二者相差不大

2、內層數(shù)據(jù)比較

     前者通過index方法把整個數(shù)組順序遍歷了一遍;

     后者調用HashSet的contains方法,實際上是調用HashMap的containKey方法,查找時是通過hash表查找,復雜度為O(1)。

接下來我們簡單看一下hash表。

hash表是一種特殊的數(shù)據(jù)結構,它同數(shù)組、鏈表以及二叉排序樹等相比較有很明顯的區(qū)別,它能夠快速定位到想要查找的記錄,而不是與表中存在的記錄的關鍵字進行比較來進行查找。這個源于Hash表設計的特殊性,它采用了函數(shù)映射的思想將記錄的存儲位置與記錄的關鍵字關聯(lián)起來,從而能夠很快速地進行查找。可以簡單理解為,以空間換時間,犧牲空間復雜度來換取時間復雜度。

hash表采用一個映射函數(shù) f : key —> address 將關鍵字映射到該記錄在表中的存儲位置,從而在想要查找該記錄時,可以直接根據(jù)關鍵字和映射關系計算出該記錄在表中的存儲位置,通常情況下,這種映射關系稱作為hash函數(shù),而通過hash函數(shù)和關鍵字計算出來的存儲位置(注意這里的存儲位置只是表中的存儲位置,并不是實際的物理地址)稱作為hash地址。

上面的圖大家應該都很熟悉,hash表的一種實現(xiàn)方式,是由數(shù)組+鏈表組成的。元素放入hash表的位置通過hash(key)%len獲得,也就是元素的key的哈希值對數(shù)組長度取模得到。

另外hash表大小的確定也很關鍵,如果hash表的空間遠遠大于最后實際存儲的記錄個數(shù),則造成了很大的空間浪費,如果選取小了的話,則容易造成沖突。在實際情況中,一般需要根據(jù)最終記錄存儲個數(shù)和關鍵字的分布特點來確定Hash表的大小。還有一種情況時可能事先不知道最終需要存儲的記錄個數(shù),則需要動態(tài)維護Hash表的容量,此時可能需要重新計算Hash地址。
當然,關于hash表要說的話太多,先簡單到此吧~~~

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關文章

  • JavaSE中比較器、深拷貝淺拷貝舉例詳解

    JavaSE中比較器、深拷貝淺拷貝舉例詳解

    在Java中一切都可以視為對象,在Java中我們經(jīng)常使用引用去操作對象,下面這篇文章主要給大家介紹了關于JavaSE中比較器、深拷貝淺拷貝的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-07-07
  • MyBatis-Plus邏輯刪除和字段自動填充的實現(xiàn)

    MyBatis-Plus邏輯刪除和字段自動填充的實現(xiàn)

    本文主要介紹了MyBatis-Plus邏輯刪除和字段自動填充的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • Java Web實現(xiàn)登錄頁面驗證碼驗證功能

    Java Web實現(xiàn)登錄頁面驗證碼驗證功能

    這篇文章主要介紹了Java Web登錄頁面驗證碼驗證功能,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-12-12
  • SpringBoot兩種方式接入DeepSeek的實現(xiàn)

    SpringBoot兩種方式接入DeepSeek的實現(xiàn)

    本文主要介紹了SpringBoot兩種方式接入DeepSeek的實現(xiàn),包括HttpClient方式和基于spring-ai-openai的方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-03-03
  • mybatis返回key value map集合方式

    mybatis返回key value map集合方式

    這篇文章主要介紹了mybatis返回key value map集合方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java中方法的重載與重寫舉例比較

    Java中方法的重載與重寫舉例比較

    這篇文章主要給大家介紹了關于Java中方法的重載與重寫的相關資料,Java中的方法重載和重寫是面向對象編程中的兩個重要概念,文中介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • 使用Maven進行版本管理的詳細步驟

    使用Maven進行版本管理的詳細步驟

    aven提供了一套強大的版本管理機制,允許開發(fā)者管理項目的版本號,并在不同的版本之間進行升級和降級,以下是如何使用Maven進行版本管理的詳細步驟和代碼示例,感興趣的小伙伴跟著小編一起來看看吧
    2024-11-11
  • springcloud?feign集成hystrix方式

    springcloud?feign集成hystrix方式

    這篇文章主要介紹了springcloud?feign集成hystrix方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • MyBatis屬性名和字段名不一致的問題解決方法

    MyBatis屬性名和字段名不一致的問題解決方法

    這篇文章給大家詳細介紹了MyBatis屬性名和字段名不一致的問題解決,文中有詳細的代碼示例和圖文展示供大家參考,對大家的學習或工作有一定的參考價值,需要的朋友可以參考下
    2023-12-12
  • 使用IDEA進行安卓開發(fā)的詳細圖文教程

    使用IDEA進行安卓開發(fā)的詳細圖文教程

    安卓開發(fā)本身就是Java開發(fā)的一個分支,我們要確保計算機已經(jīng)安裝好JDK并做好了相關的配置,下面這篇文章主要給大家介紹了關于如何使用IDEA進行安卓開發(fā)的詳細圖文教程,需要的朋友可以參考下
    2023-04-04

最新評論

鄯善县| 肇州县| 玉林市| 东海县| 岳西县| 屯门区| 木兰县| 本溪市| 五大连池市| 信阳市| 安仁县| 莒南县| 都昌县| 建始县| 德兴市| 富裕县| 台山市| 青田县| 连云港市| 介休市| 长治市| 崇信县| 平乐县| 富阳市| 衡阳县| 延庆县| 海南省| 广丰县| 麦盖提县| 保康县| 台中市| 沧州市| 桐柏县| 米林县| 武义县| 蒙山县| 通海县| 精河县| 定南县| 铁岭市| 湛江市|