欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中兩個(gè)List之間的比較方法(差集、交集和并集)

 更新時(shí)間:2022年06月16日 09:20:17   作者:程序猿不源  
在業(yè)務(wù)的開發(fā)過程中會(huì)經(jīng)常用到兩個(gè)List集合相互取值的情況,下面這篇文章主要給大家介紹了關(guān)于Java中兩個(gè)List之間的比較方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

實(shí)現(xiàn)比較兩個(gè)List之間的差異,包括獲取兩List的差集,交集,并集(不去重&去重)的API解法和優(yōu)化解法的解決方案。

求差集

/**
 * 差集(基于API解法) 適用于小數(shù)據(jù)量
 * 求List1中有的但是List2中沒有的元素
 * 時(shí)間復(fù)雜度 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中沒有的元素
 * 空間換時(shí)間降低時(shí)間復(fù)雜度
 * 時(shí)間復(fù)雜度O(Max(list1.size(),list2.size()))
 */
public static List<String> subList1(List<String> list1, List<String> list2) {
    //空間換時(shí)間 降低時(shí)間復(fù)雜度
    Map<String, String> tempMap = new HashMap<>();
    for(String str:list2){
        tempMap.put(str,str);
    }
    //LinkedList 頻繁添加刪除 也可以ArrayList容量初始化為List1.size(),防止數(shù)據(jù)量過大時(shí)頻繁擴(kuò)容以及數(shù)組復(fù)制
    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中都有的元素
 * 時(shí)間復(fù)雜度 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中都有的元素
 * 時(shí)間復(fù)雜度O(Max(list1.size(),list2.size()))
 */
public static List<String> intersectList1(List<String> list1, List<String> list2){
    //空間換時(shí)間 降低時(shí)間復(fù)雜度
    Map<String, String> tempMap = new HashMap<>();
    for(String str:list2){
        tempMap.put(str,str);
    }
    //LinkedList 頻繁添加刪除 也可以ArrayList容量初始化為List1.size(),防止數(shù)據(jù)量過大時(shí)頻繁擴(kuò)容以及數(shù)組復(fù)制
    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 不考慮去除重復(fù)元素
 * 數(shù)組擴(kuò)容 數(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 去除重復(fù)元素
 * 時(shí)間復(fù)雜度主要取決于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 去除重復(fù)元素
 */
public static List<String> distinctMergeList1(List<String> list1, List<String> list2){
    //第一步 先求出list1與list2的差集
    list1 = subList2(list1,list2);
    //第二部 再合并list1和list2
    list1.addAll(list2);
    return list1;
}

實(shí)際業(yè)務(wù)場景

根據(jù)客戶需求,業(yè)務(wù)提交審核需要很直觀的看到此次提交的數(shù)據(jù)關(guān)聯(lián)產(chǎn)品的狀態(tài)變更。

第一種情況:新增的渠道授權(quán)關(guān)聯(lián)的產(chǎn)品,所有的授權(quán)產(chǎn)品均為新增;

第二種情況:已審核通過的渠道授權(quán)重新提交授權(quán)審核的,要直觀的標(biāo)記出此次提交審核渠道關(guān)聯(lián)授權(quán)產(chǎn)品新增了那些,刪除了那些,更改了那些等信息;

第三種情況:作廢渠道提交的審核要標(biāo)注出所有的關(guān)聯(lián)授權(quán)產(chǎn)品為刪除狀態(tài)。

授權(quán)關(guān)聯(lián)產(chǎn)品為申請表單中一對多關(guān)聯(lián)表,前端展示根據(jù)數(shù)據(jù)的不同狀態(tài)展示不同的樣式:

  • 新增授權(quán)產(chǎn)品顯示為紅色
  • 刪除授權(quán)產(chǎn)品顯示為刪除線樣式(中劃線 )
  • 更新授權(quán)產(chǎn)品顯示標(biāo)注紅色*號(hào)

建立關(guān)聯(lián)產(chǎn)品Vo

首先模擬建立一個(gè)產(chǎn)品的實(shí)體,此處只簡單列入幾個(gè)屬性,在比較所關(guān)聯(lián)產(chǎn)品信息是否是變更狀態(tài)的時(shí)候根據(jù)實(shí)際業(yè)務(wù)需要需重寫 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è)務(wù)代碼實(shí)現(xiàn)

業(yè)務(wù)實(shí)現(xiàn)主要通過 空間換時(shí)間 方式降低時(shí)間復(fù)雜度,先把List轉(zhuǎn)為Map,利用map的 get 和 containsKey 方法理想情況下O(1)的時(shí)間復(fù)雜度降低嵌套的兩次List遍歷。

/**
 * 渠道授權(quán)新提交關(guān)聯(lián)授權(quán)產(chǎn)品 與 歷史已審批授權(quán)信息對比處理標(biāo)注授權(quán)產(chǎn)品的狀態(tài)信息<br/>
 * 前端可以根據(jù)不同的數(shù)據(jù)狀態(tài)顯示不同的樣式<br/>
 * 用于審核人員直接看到此次提交審核新增了那些授權(quán),取消了那些授權(quán),更改了那些授權(quán)
 * @param oldList  原始關(guān)聯(lián)授權(quán)產(chǎn)品列表
 * @param newList  提交關(guān)聯(lián)授權(quán)產(chǎn)品列表
 * @return
 */
public List<ProductVo> productStatusHandle(List<ProductVo> oldList,List<ProductVo> newList){
    //原始關(guān)聯(lián)授權(quán)產(chǎn)品為空 并且 新關(guān)聯(lián)授權(quán)產(chǎn)品為空(基本不存在此場景)
    if((oldList == null || oldList.isEmpty()) && (newList == null || newList.isEmpty())){
        return Collections.emptyList();
    }
    //原始關(guān)聯(lián)授權(quán)產(chǎn)品為空 則提交關(guā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());
    }
    //提交關(guān)聯(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());
    }
    //原始關(guān)聯(lián)授權(quán)產(chǎn)品與此次提交關(guān)聯(lián)授權(quán)產(chǎn)品均不為空
    List<ProductVo> resList = new LinkedList<>();
    //空間換時(shí)間 降低時(shí)間復(fù)雜度
    //說明:list中不會(huì)存在重復(fù)(ID相同)的授權(quán)產(chǎn)品 否則此toMap收集會(huì)拋出異常
    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());
        //提交關(guān)聯(lián)授權(quán)產(chǎn)品在原始關(guā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);
    }
    //原始關(guān)聯(lián)授權(quán)產(chǎn)品是否存在已取消的情況
    for(ProductVo vo:oldList){
        if(!newMap.containsKey(vo.getId())){
            vo.setStatus("delete");
            resList.add(vo);
        }
    }
    return resList;
}

總結(jié)

到此這篇關(guān)于Java中兩個(gè)List之間的比較方法的文章就介紹到這了,更多相關(guān)Java中List比較內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 異步編程實(shí)踐_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java 異步編程實(shí)踐_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    異步編程提供了一個(gè)非阻塞的,事件驅(qū)動(dòng)的編程模型。下面通過本文給大家介紹Java 異步編程實(shí)踐,感興趣的的朋友一起看看吧
    2017-05-05
  • SpringBoot整合Activiti工作流框架的使用

    SpringBoot整合Activiti工作流框架的使用

    本文主要介紹了SpringBoot整合Activiti工作流框架的使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 一文詳解Spring?security框架的使用

    一文詳解Spring?security框架的使用

    Spring?Security是一個(gè)基于Spring框架的安全認(rèn)證和授權(quán)框架,它提供了一套全面的安全解決方案,可以在Web應(yīng)用、移動(dòng)應(yīng)用和Web服務(wù)等不同場景下使用。本文就來詳細(xì)聊聊它的使用吧
    2023-03-03
  • mybatis插入后返回主鍵id的3種方式圖解

    mybatis插入后返回主鍵id的3種方式圖解

    這篇文章主要給大家介紹了關(guān)于mybatis插入后返回主鍵id的3種方式,很多時(shí)候,在向數(shù)據(jù)庫插入數(shù)據(jù)時(shí),需要保留插入數(shù)據(jù)的,以便進(jìn)行后續(xù)的操作或者將存入其他表作為外鍵,需要的朋友可以參考下
    2023-08-08
  • SpringBoot學(xué)習(xí)系列之MyBatis Plus整合封裝的實(shí)例詳解

    SpringBoot學(xué)習(xí)系列之MyBatis Plus整合封裝的實(shí)例詳解

    MyBatis-Plus是一款MyBatis的增強(qiáng)工具(簡稱MP),為簡化開發(fā)、提高效率,這篇文章給大家介紹MyBatis Plus整合封裝的實(shí)例詳解,感興趣的朋友跟隨小編一起看看吧
    2020-08-08
  • java實(shí)現(xiàn)簡單的加減乘除計(jì)算器

    java實(shí)現(xiàn)簡單的加減乘除計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡單的加減乘除計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 鎖超時(shí)發(fā)現(xiàn)parallelStream并行流線程上下文坑解決

    鎖超時(shí)發(fā)現(xiàn)parallelStream并行流線程上下文坑解決

    這篇文章主要為大家介紹了鎖超時(shí)發(fā)現(xiàn)parallelStream并行流線程上下文坑解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java練習(xí)之潛艇小游戲的實(shí)現(xiàn)

    Java練習(xí)之潛艇小游戲的實(shí)現(xiàn)

    這篇文章主要和大家分享一個(gè)Java小練習(xí)——利用Java編寫一個(gè)潛艇小游戲,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-03-03
  • 使用javaMail實(shí)現(xiàn)發(fā)送郵件

    使用javaMail實(shí)現(xiàn)發(fā)送郵件

    這篇文章主要為大家詳細(xì)介紹了使用javaMail實(shí)現(xiàn)發(fā)送郵件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 關(guān)于Java反射機(jī)制 你需要知道的事情

    關(guān)于Java反射機(jī)制 你需要知道的事情

    這篇文章主要介紹了Java反射機(jī)制的相關(guān)內(nèi)容,涉及了class類的動(dòng)態(tài)加載,獲取成員變量、構(gòu)造函數(shù)信息等信息,需要的朋友可以參考下。
    2017-09-09

最新評論