JAVA 容器集合+數據結構 模擬SQL實現交併差統計等操做

JAVA代碼一樣能夠經過合理運用數據結構和算法的特色實現SQL中的大部分操做,例如:JOIN ON ,WHERE ,UNION ,IN/NOT IN ,GROUPBY ,TOP ,LIMIT 等等java

大數據量的 去重、交併差.....等集合操做,均可以適當藉助中間容器實現,而且合理運用不一樣的數據結構的特色作中間容器,能夠大大提升效率優化時間複雜度。儘量避免循環嵌套的遍歷,形成倍數級別(n行 x m行)的時間複雜度。注意根據須要重寫hashcode()和equals()。還要考慮中間容器構造的時間和空間消耗算法

JDK提供了一些原生方法:retainAll,addAll,removeAll,可是有些效率通常sql

數據結構的特色:Hash、Tree結構適合查找頻繁的場景,Array結構適合隨記、下標訪問,Set能夠去重等等,堆作TOP。數據庫

List<List/Set/Map/Object>,Map<key,List/Set/Map/Object> 將相同特性的放在一個List中,實現一KEY多值、分組等。方便查找過濾分組。以及實現相似矩陣等更復雜數據結構數據結構

在合適的場景也能夠加入多線程處理提升速度。多線程

例如併發

如下只是我的意見,有其餘更好思路但願你們留言數據結構和算法

求兩個List的交集/差集/查重: 其核心是查找,能夠藉助HashSet/Map將大List放入其中做爲查詢字典,另外一個List去HashSet中查找是否存在。此思路藉助HASH表結構完成查找,避免循環嵌套的遍歷,提升了對比效率。工具

求兩個List的徹底差集:能夠藉助Map,將大List做爲K放入其中,V記錄出現次數。另外一個List去Map中查找,存在則更新V=2,不存在則做爲K放入其中。最後只須要找出Map中V爲1的K。測試

給List<User>按照年齡分組:遍歷List<User> 保存到HashMap<age,List<User>>中。分組後的值爲HashMap.values()=List<List<User>>。JDK8可直接使用Stream分組

用Java代碼替換Sql語句:有時考慮到數據庫壓力和併發問題,只能執行簡單的Sql語句返回基礎表數據。這時須要在Java的Service層中處理這些原始數據List,代替SQL中的操做。

Distinct:去重。將List保存到Set中實現去重。

Sum:統計出現次數。能夠藉助HashMap<T,Integer> 結構,遍歷List<T>去查找HashMap中更新Integer++。

In/Not in: 交集差集,其核心是查找,能夠藉助HashSet/Map將大List放入其中做爲查詢字典,另外一個List去HashSet中查找是否存在。此思路藉助HASH表結構完成查找,避免循環嵌套的遍歷,提升了對比效率。

Where:至關於過濾集合。推薦Guava庫提供的過濾方法。

Groupby分組。JDK8可直接使用Stream分組,或經過Map<分組id,List>結構保存。

Join關聯(一對一,一對多),能夠將做爲查詢字典的集合放入HashMap中,key做用Join On關聯條件,查找並更信息相應屬性值/引用。若是是多條件關聯,能夠考慮條件合併,或是map嵌套Map<on條件1,Map<on條件2,表Object>>

class 主表Object{
 
    子表Object obj; //一對一
 
    List<子表Object> list; //一對多 
}

一對多方案:

方案1:HashMap字典主表List。將List<主表Object>放入HashMap<on條件,主表Object>中。遍歷List<子表Object>,經過on條件從HashMap中找到主表Object,並放入其List<子表Object>中。

經測試:主表4萬,子表8萬數據量,子表無索引。 使用java與原生sql執行join對比,記錄從查詢到完成時間差。java速度沒有不慢於sql。

方案2:HashMap分組子表List。與方案1思路類似,只是改爲Map分組子表,將List<子表Object>分組爲Map<on條件,List<子表Object>>結構,遍歷List<主表Object>去分組後的Map中找對應List。

方案3:過濾子表List。遍歷List<主表Object>,按on條件使用Guava庫方法過濾List<子表Object>,放入主表Object中。

方案4:同步下標遍歷。假設工號爲關聯條件,ArrayList<主表Object>和List<子表Object> 都按照工號排序,用一個int index=0記錄ArrayList<主表Object>當前下標。遍歷List<子表Object>,把子表Object放入ArrayList<主表Object>.get(index)中。當判斷 子表Object.工號<>ArrayList<主表Object>.get(index).工號 時下移主表下標 index++。這樣只須要遍歷List<子表Object>和ArrayList<主表Object>都只遍歷一次。前提是主/子都按照相同條件順序排序。

//方案4 僞代碼 
//一對多場景下,主表爲小表
List<主表Object> list1; //按照id排序
List<子表Object> list2; //按照id排序

主表Object o1;
子表Object o2;
int sub_index=0;
Iterator iter1 = list1.iterator();
//外循環小表
while(iter1.hasNext()){
     o1 = (主表Object) iter1.next();
     while(sub_index<list2.size()){ 
           o2=list2.get(sub_index); //取得子表當前下標位置元素
           if (o2.getid().equals(o1.getid())){  //判斷關聯條件
               o1.getSubList.add(o2);
               sub_index++; //更新子表當前下標
           }else{
               break;
           }           
     }     
}

頻繁須要查詢的集合最好使用Hash、Tree結構保存
 

Top K 問題

其本質上是排序問題,經常使用思路:快速排序(求小 左遞歸,求大 右遞歸)、堆排序(適合大數據量) .。

堆排序雖然自己速度沒有快排和歸併這種分治排序快,可是當統計外部大數據量時,求TOP K只須要創建容量爲K的堆,很是節省內存開銷。

JAVA中PriorityQueue 優先級隊列是小根堆結構,可是能夠經過comparator自定義大小,轉換成大根堆模式。

PriorityQueue(int initialCapacity,Comparator<? super E> comparator)
 

集合第三方JAR推薦

google.Guava , Apache Commons Collections 包含不少高效的集合操做API和新類型的數據結構。

推薦Guava,經測試平均執行效率高於JDKAPI(Lists,Sets,Maps,Collections2等工具類中提供了包括集合交併差過濾等多種高效操做)。並且除了集合,還有不少高效簡單的工具類,涉及String,Object,I/O等等

https://blog.csdn.net/dgeek/article/details/76221746  

相關文章
相關標籤/搜索