Java 獲取兩個(gè)List的交集和差集,以及應(yīng)用場景操作
背景介紹
在實(shí)際項(xiàng)目中,特別是一些管理后臺(tái)類的項(xiàng)目,會(huì)遇到底層數(shù)據(jù)是按照一對(duì)多關(guān)系的數(shù)據(jù)表存儲(chǔ)的管理界面。列表頁是一對(duì)多關(guān)系中一對(duì)應(yīng)的數(shù)據(jù)列表,二級(jí)的詳情頁中是一對(duì)多關(guān)系中多對(duì)應(yīng)的多條數(shù)據(jù)展示。通常二級(jí)頁面是能夠增、刪、改數(shù)據(jù)的編輯頁面,在點(diǎn)擊保存提交數(shù)據(jù)后,服務(wù)器端需要插入新增的數(shù)據(jù),刪除要?jiǎng)h除的數(shù)據(jù),更新改變的數(shù)據(jù)。
例如,在汽車電商領(lǐng)域,如果要實(shí)現(xiàn)一輛車型在不同省份有不同的價(jià)格行情,就需要有一個(gè)車價(jià)管理的后臺(tái)管理界面。每輛車對(duì)應(yīng)的詳情界面管理各省價(jià)格行情,增加該車在某個(gè)省份的行情,或者更新某個(gè)省份的行情,或者該車暫時(shí)去除某個(gè)省份的行情等功能,需要服務(wù)器端保證正確地?cái)?shù)據(jù)存儲(chǔ)。
交集:指的是兩個(gè)List對(duì)象中都有的元素。
差集:指的是一個(gè)List對(duì)象中有,而另一個(gè)List對(duì)象中沒有的元素。
轉(zhuǎn)化為一般問題
在車價(jià)管理的車輛詳情頁面點(diǎn)擊保存各省行情按鈕后,請(qǐng)求會(huì)傳送一組數(shù)據(jù)到服務(wù)端,服務(wù)端把這組數(shù)據(jù)保存到一個(gè)List對(duì)象中。然后從數(shù)據(jù)庫中獲取該車型之前的各省行情數(shù)據(jù)并保存到List對(duì)象中,那么怎么找出哪些數(shù)據(jù)是要新增的,哪些數(shù)據(jù)是要?jiǎng)h除的,又有哪些數(shù)據(jù)是要更新的呢?
如果客戶端傳送的數(shù)據(jù)中有的省份行情數(shù)據(jù),而數(shù)據(jù)庫中沒有該省行情數(shù)據(jù)記錄,則這些數(shù)據(jù)是要插入數(shù)據(jù)庫中的。如果客戶端傳送的數(shù)據(jù)有的省份行情數(shù)據(jù),數(shù)據(jù)庫中也有改省的行情數(shù)據(jù),則這些數(shù)據(jù)是要更新的數(shù)據(jù)。如果數(shù)據(jù)庫中有的省份數(shù)據(jù),而客戶端傳送的數(shù)據(jù)中沒有改省份數(shù)據(jù),則這些數(shù)據(jù)是要?jiǎng)h除的。
經(jīng)過上述分析,不難發(fā)現(xiàn)就是找出兩個(gè)List對(duì)象的交集和差集。例如,a為客戶端傳送的數(shù)據(jù)List對(duì)象,b為從數(shù)據(jù)庫中獲取的List對(duì)象。 a中有的元素,而b中沒有的元素就是要插入數(shù)據(jù)庫中的數(shù)據(jù),即a與b的差集。a和b共有的元素就是要更新的數(shù)據(jù),即a與b的交集。b中有的元素,a中沒有的就是要?jiǎng)h除的數(shù)據(jù),即b與a的差集。
程序代碼
程序的大致思路是:利用LinkedHashMap key值的唯一性和順序存儲(chǔ)的特性,把provinceId作為key值,先用一個(gè)map添加一個(gè)List元素,然后再去比較另一個(gè)List對(duì)象中的元素,找出provinceId相同的對(duì)象和只有b中才有的對(duì)象。map中去除相同的key值的對(duì)象,剩余的就是a中獨(dú)有的元素。
各省行情類:
public class CarProvinceMarket { private Integer id; private Integer carId; private Integer provinceId; private Double price; private Integer createdBy; public Integer getCreatedBy() { return createdBy; } public void setCreatedBy(Integer createdBy) { this.createdBy = createdBy; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getCarId() { return carId; } public void setCarId(Integer carId) { this.carId = carId; } public Integer getProvinceId() { return provinceId; } public void setProvinceId(Integer provinceId) { this.provinceId = provinceId; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } }
求兩個(gè)List對(duì)象交集、差集:
public class ListOperation { public static void sameAndDifferentOperation(List<CarProvinceMarket> a, List<CarProvinceMarket> b, List<CarProvinceMarket> sameItems, List<CarProvinceMarket> onlyAItems, List<CarProvinceMarket> onlyBItems){ if (a.isEmpty() && b.isEmpty()){ return; } LinkedHashMap<Integer, CarProvinceMarket> map = new LinkedHashMap<>(); LinkedHashMap<Integer, CarProvinceMarket> sameMap = new LinkedHashMap<>(); LinkedHashMap<Integer, CarProvinceMarket> onlyBMap = new LinkedHashMap<>(); for (CarProvinceMarket item: a){ map.put(item.getProvinceId(), item); } for (CarProvinceMarket item: b){ if (map.containsKey(item.getProvinceId())){ //如果要更新a中的記錄,則要更新map中的元素,并添加到sameMap CarProvinceMarket carProvinceMarket = map.get(item.getProvinceId()); carProvinceMarket.setPrice(100000d); sameMap.put(item.getProvinceId(), carProvinceMarket); }else { //新建的元素,需要設(shè)置相關(guān)成員變量 item.setCreatedBy(4); onlyBMap.put(item.getProvinceId(),item); } } sameItems.addAll(sameMap.values()); onlyBItems.addAll(onlyBMap.values()); for (CarProvinceMarket item: sameItems){ map.remove(item.getProvinceId()); } onlyAItems.addAll(map.values()); } public static void main(String [] args){ ArrayList<CarProvinceMarket> aCarProMar = new ArrayList<>(); ArrayList<CarProvinceMarket> bCarProMar = new ArrayList<>(); for (int i=0; i<1000000; i++){ CarProvinceMarket aCar = new CarProvinceMarket(); aCar.setProvinceId((i + 1)/2); aCarProMar.add(aCar); CarProvinceMarket bCar = new CarProvinceMarket(); bCar.setProvinceId((i + 2)/2); bCarProMar.add(bCar); } LinkedList<CarProvinceMarket> sameItems = new LinkedList<>(); LinkedList<CarProvinceMarket> onlyAItems = new LinkedList<>(); LinkedList<CarProvinceMarket> onlyBItems = new LinkedList<>(); Long start = System.currentTimeMillis(); sameAndDifferentOperation(aCarProMar, bCarProMar, sameItems, onlyAItems, onlyBItems); System.out.println("time = " + (System.currentTimeMillis() - start)); } }
總結(jié)
在開發(fā)過程中,遇到問題要找出問題的一般性,轉(zhuǎn)化概念,理解本質(zhì),方能解決問題。
代碼鏈接: github
以上這篇Java 獲取兩個(gè)List的交集和差集,以及應(yīng)用場景操作就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用spring?security?BCryptPasswordEncoder接入系統(tǒng)
這篇文章主要介紹了使用spring?security?BCryptPasswordEncoder接入系統(tǒng)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Java的分支結(jié)構(gòu)與循環(huán)你知道多少
這篇文章主要為大家詳細(xì)介紹了Java的分支結(jié)構(gòu)與循環(huán),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02SpringBoot實(shí)現(xiàn)Thymeleaf驗(yàn)證碼生成
本文使用SpringBoot實(shí)現(xiàn)Thymeleaf驗(yàn)證碼生成,使用后臺(tái)返回驗(yàn)證碼圖片,驗(yàn)證碼存到session中后端實(shí)現(xiàn)校驗(yàn),前端只展示驗(yàn)證碼圖片。感興趣的可以了解下2021-05-05SpringBoot+jpa配置如何根據(jù)實(shí)體類自動(dòng)創(chuàng)建表
這篇文章主要介紹了SpringBoot+jpa配置如何根據(jù)實(shí)體類自動(dòng)創(chuàng)建表,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11Java均攤復(fù)雜度和防止復(fù)雜度的震蕩原理分析
這篇文章主要介紹了Java均攤復(fù)雜度和防止復(fù)雜度的震蕩,結(jié)合實(shí)例形式分析了Java均攤復(fù)雜度和防止復(fù)雜度的震蕩相關(guān)概念、原理、實(shí)現(xiàn)方法與注意事項(xiàng),需要的朋友可以參考下2020-03-03java 開發(fā)中網(wǎng)絡(luò)編程之IP、URL詳解及實(shí)例代碼
這篇文章主要介紹了java 開發(fā)中網(wǎng)絡(luò)編程之IP、URL詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03