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