Java中兩個List之間的比較方法(差集、交集和并集)
實現(xiàn)比較兩個List之間的差異,包括獲取兩List的差集,交集,并集(不去重&去重)的API解法和優(yōu)化解法的解決方案。
求差集
/**
* 差集(基于API解法) 適用于小數(shù)據(jù)量
* 求List1中有的但是List2中沒有的元素
* 時間復雜度 O(list1.size() * list2.size())
*/
public static List<String> subList(List<String> list1, List<String> list2) {
list1.removeAll(list2);
return list1;
}
/**
* 差集(基于常規(guī)解法)優(yōu)化解法1 適用于中等數(shù)據(jù)量
* 求List1中有的但是List2中沒有的元素
* 空間換時間降低時間復雜度
* 時間復雜度O(Max(list1.size(),list2.size()))
*/
public static List<String> subList1(List<String> list1, List<String> list2) {
//空間換時間 降低時間復雜度
Map<String, String> tempMap = new HashMap<>();
for(String str:list2){
tempMap.put(str,str);
}
//LinkedList 頻繁添加刪除 也可以ArrayList容量初始化為List1.size(),防止數(shù)據(jù)量過大時頻繁擴容以及數(shù)組復制
List<String> resList = new LinkedList<>();
for(String str:list1){
if(!tempMap.containsKey(str)){
resList.add(str);
}
}
return resList;
}
/**
* 差集(基于java8新特性)優(yōu)化解法2 適用于大數(shù)據(jù)量
* 求List1中有的但是List2中沒有的元素
*/
public static List<String> subList2(List<String> list1, List<String> list2) {
Map<String, String> tempMap = list2.parallelStream().collect(Collectors.toMap(Function.identity(), Function.identity(), (oldData, newData) -> newData));
return list1.parallelStream().filter(str->{
return !tempMap.containsKey(str);
}).collect(Collectors.toList());
}
求交集
/**
* 交集(基于API解法) 適用于小數(shù)據(jù)量
* 求List1和List2中都有的元素
* 時間復雜度 O(list1.size() * list2.size())
*/
public static List<String> intersectList(List<String> list1, List<String> list2){
list1.retainAll(list2);
return list1;
}
/**
* 交集(基于常規(guī)解法) 優(yōu)化解法1 適用于中等數(shù)據(jù)量
* 求List1和List2中都有的元素
* 時間復雜度O(Max(list1.size(),list2.size()))
*/
public static List<String> intersectList1(List<String> list1, List<String> list2){
//空間換時間 降低時間復雜度
Map<String, String> tempMap = new HashMap<>();
for(String str:list2){
tempMap.put(str,str);
}
//LinkedList 頻繁添加刪除 也可以ArrayList容量初始化為List1.size(),防止數(shù)據(jù)量過大時頻繁擴容以及數(shù)組復制
List<String> resList = new LinkedList<>();
for(String str:list1){
if(tempMap.containsKey(str)){
resList.add(str);
}
}
return resList;
}
/**
* 交集(基于java8新特性)優(yōu)化解法2 適用于大數(shù)據(jù)量
* 求List1和List2中都有的元素
*/
public static List<String> intersectList2(List<String> list1, List<String> list2){
Map<String, String> tempMap = list2.parallelStream().collect(Collectors.toMap(Function.identity(), Function.identity(), (oldData, newData) -> newData));
return list1.parallelStream().filter(str->{
return tempMap.containsKey(str);
}).collect(Collectors.toList());
}
求并集(不去重)
/**
* 并集(不去重)
* 合并list1和list2 不考慮去除重復元素
* 數(shù)組擴容 數(shù)組copy
* @param list1
* @param list2
* @return
*/
public static List<String> mergeList(List<String> list1, List<String> list2){
list1.addAll(list2);
return list1;
}
求并集(去重)
/**
* 并集(去重) 基于API解法
* 合并list1和list2 去除重復元素
* 時間復雜度主要取決于removeAll 取差集 O(list1.size() * list2.size())
*/
public static List<String> distinctMergeList(List<String> list1, List<String> list2){
//第一步 先求出list1與list2的差集
list1.removeAll(list2);
//第二部 再合并list1和list2
list1.addAll(list2);
return list1;
}
/**
* 并集(去重) 基于Java8新特性 適用于大數(shù)據(jù)量
* 合并list1和list2 去除重復元素
*/
public static List<String> distinctMergeList1(List<String> list1, List<String> list2){
//第一步 先求出list1與list2的差集
list1 = subList2(list1,list2);
//第二部 再合并list1和list2
list1.addAll(list2);
return list1;
}
實際業(yè)務場景
根據(jù)客戶需求,業(yè)務提交審核需要很直觀的看到此次提交的數(shù)據(jù)關聯(lián)產(chǎn)品的狀態(tài)變更。
第一種情況:新增的渠道授權(quán)關聯(lián)的產(chǎn)品,所有的授權(quán)產(chǎn)品均為新增;
第二種情況:已審核通過的渠道授權(quán)重新提交授權(quán)審核的,要直觀的標記出此次提交審核渠道關聯(lián)授權(quán)產(chǎn)品新增了那些,刪除了那些,更改了那些等信息;
第三種情況:作廢渠道提交的審核要標注出所有的關聯(lián)授權(quán)產(chǎn)品為刪除狀態(tài)。
授權(quán)關聯(lián)產(chǎn)品為申請表單中一對多關聯(lián)表,前端展示根據(jù)數(shù)據(jù)的不同狀態(tài)展示不同的樣式:
- 新增授權(quán)產(chǎn)品顯示為紅色
- 刪除授權(quán)產(chǎn)品顯示為刪除線樣式(中劃線 )
- 更新授權(quán)產(chǎn)品顯示標注紅色*號
建立關聯(lián)產(chǎn)品Vo
首先模擬建立一個產(chǎn)品的實體,此處只簡單列入幾個屬性,在比較所關聯(lián)產(chǎn)品信息是否是變更狀態(tài)的時候根據(jù)實際業(yè)務需要需重寫 hashCode 和 equals 方法。
class ProductVo{
private String id;
private String name;
//其他屬性不在列入
//數(shù)據(jù)狀態(tài)(新增:insert; 更新:update; 刪除:delete)
private String status;
//get set 省略
//如有必要重寫hashCode equals
}
業(yè)務代碼實現(xiàn)
業(yè)務實現(xiàn)主要通過 空間換時間 方式降低時間復雜度,先把List轉(zhuǎn)為Map,利用map的 get 和 containsKey 方法理想情況下O(1)的時間復雜度降低嵌套的兩次List遍歷。
/**
* 渠道授權(quán)新提交關聯(lián)授權(quán)產(chǎn)品 與 歷史已審批授權(quán)信息對比處理標注授權(quán)產(chǎn)品的狀態(tài)信息<br/>
* 前端可以根據(jù)不同的數(shù)據(jù)狀態(tài)顯示不同的樣式<br/>
* 用于審核人員直接看到此次提交審核新增了那些授權(quán),取消了那些授權(quán),更改了那些授權(quán)
* @param oldList 原始關聯(lián)授權(quán)產(chǎn)品列表
* @param newList 提交關聯(lián)授權(quán)產(chǎn)品列表
* @return
*/
public List<ProductVo> productStatusHandle(List<ProductVo> oldList,List<ProductVo> newList){
//原始關聯(lián)授權(quán)產(chǎn)品為空 并且 新關聯(lián)授權(quán)產(chǎn)品為空(基本不存在此場景)
if((oldList == null || oldList.isEmpty()) && (newList == null || newList.isEmpty())){
return Collections.emptyList();
}
//原始關聯(lián)授權(quán)產(chǎn)品為空 則提交關聯(lián)授權(quán)產(chǎn)品全部為新增
if(oldList == null || oldList.isEmpty()){
return newList.stream().map(vo->{
vo.setStatus("insert");
return vo;
}).collect(Collectors.toList());
}
//提交關聯(lián)授權(quán)產(chǎn)品為空 則刪除之前所有的產(chǎn)品授權(quán)
if(newList == null || newList.isEmpty()){
return oldList.stream().map(vo->{
vo.setStatus("delete");
return vo;
}).collect(Collectors.toList());
}
//原始關聯(lián)授權(quán)產(chǎn)品與此次提交關聯(lián)授權(quán)產(chǎn)品均不為空
List<ProductVo> resList = new LinkedList<>();
//空間換時間 降低時間復雜度
//說明:list中不會存在重復(ID相同)的授權(quán)產(chǎn)品 否則此toMap收集會拋出異常
Map<String, ProductVo> oldMap = oldList.stream().collect(Collectors.toMap(ProductVo::getId, Function.identity()));
Map<String, ProductVo> newMap = newList.stream().collect(Collectors.toMap(ProductVo::getId, Function.identity()));
for(ProductVo vo:newList){
ProductVo productVo = oldMap.get(vo.getId());
//提交關聯(lián)授權(quán)產(chǎn)品在原始關聯(lián)授權(quán)產(chǎn)品
if(productVo != null){
if(!vo.equals(productVo)){//重寫hashCode與equals自定義規(guī)則 用于判定是否數(shù)據(jù)更新
vo.setStatus("update");
}
}else{//提交審核數(shù)據(jù)不在舊數(shù)據(jù)之列
vo.setStatus("insert");
}
resList.add(vo);
}
//原始關聯(lián)授權(quán)產(chǎn)品是否存在已取消的情況
for(ProductVo vo:oldList){
if(!newMap.containsKey(vo.getId())){
vo.setStatus("delete");
resList.add(vo);
}
}
return resList;
}總結(jié)
到此這篇關于Java中兩個List之間的比較方法的文章就介紹到這了,更多相關Java中List比較內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot學習系列之MyBatis Plus整合封裝的實例詳解
MyBatis-Plus是一款MyBatis的增強工具(簡稱MP),為簡化開發(fā)、提高效率,這篇文章給大家介紹MyBatis Plus整合封裝的實例詳解,感興趣的朋友跟隨小編一起看看吧2020-08-08
鎖超時發(fā)現(xiàn)parallelStream并行流線程上下文坑解決
這篇文章主要為大家介紹了鎖超時發(fā)現(xiàn)parallelStream并行流線程上下文坑解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08

