Java 获取两个List的交集和差集,以及应用场景操作
作者:回归心灵 发布时间:2021-11-21 17:49:43
背景介绍
在实际项目中,特别是一些管理后台类的项目,会遇到底层数据是按照一对多关系的数据表存储的管理界面。列表页是一对多关系中一对应的数据列表,二级的详情页中是一对多关系中多对应的多条数据展示。通常二级页面是能够增、删、改数据的编辑页面,在点击保存提交数据后,服务器端需要插入新增的数据,删除要删除的数据,更新改变的数据。
例如,在汽车电商领域,如果要实现一辆车型在不同省份有不同的价格行情,就需要有一个车价管理的后台管理界面。每辆车对应的详情界面管理各省价格行情,增加该车在某个省份的行情,或者更新某个省份的行情,或者该车暂时去除某个省份的行情等功能,需要服务器端保证正确地数据存储。
交集:指的是两个List对象中都有的元素。
差集:指的是一个List对象中有,而另一个List对象中没有的元素。
转化为一般问题
在车价管理的车辆详情页面点击保存各省行情按钮后,请求会传送一组数据到服务端,服务端把这组数据保存到一个List对象中。然后从数据库中获取该车型之前的各省行情数据并保存到List对象中,那么怎么找出哪些数据是要新增的,哪些数据是要删除的,又有哪些数据是要更新的呢?
如果客户端传送的数据中有的省份行情数据,而数据库中没有该省行情数据记录,则这些数据是要插入数据库中的。如果客户端传送的数据有的省份行情数据,数据库中也有改省的行情数据,则这些数据是要更新的数据。如果数据库中有的省份数据,而客户端传送的数据中没有改省份数据,则这些数据是要删除的。
经过上述分析,不难发现就是找出两个List对象的交集和差集。例如,a为客户端传送的数据List对象,b为从数据库中获取的List对象。 a中有的元素,而b中没有的元素就是要插入数据库中的数据,即a与b的差集。a和b共有的元素就是要更新的数据,即a与b的交集。b中有的元素,a中没有的就是要删除的数据,即b与a的差集。
程序代码
程序的大致思路是:利用LinkedHashMap key值的唯一性和顺序存储的特性,把provinceId作为key值,先用一个map添加一个List元素,然后再去比较另一个List对象中的元素,找出provinceId相同的对象和只有b中才有的对象。map中去除相同的key值的对象,剩余的就是a中独有的元素。
各省行情类:
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;
}
}
求两个List对象交集、差集:
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 {
//新建的元素,需要设置相关成员变量
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));
}
}
总结
在开发过程中,遇到问题要找出问题的一般性,转化概念,理解本质,方能解决问题。
代码链接: github
来源:https://blog.csdn.net/u010657094/article/details/78906641


猜你喜欢
- 本文实例讲述了Java递归算法。分享给大家供大家参考,具体如下:1.实现1到100的和,用递归实现public class Recursio
- 你是否受够了每次修改静态文件都要重启服务器?有时候在一些公司前后端的职责没有那么的明确,往往后台人员也要去写一些页面,像jsp页面,或者其他
- 前言我曾经在一篇介绍 Compose Navigation 的文章 中提到了 Navigation 的状态保存实际是由 rememberSa
- 最近项目中遇到一个问题,在用户没填数据的时候,我们需要接收从前端传过来的对象为null,但是前端说他们一个一个判断特别麻烦,只能传个空对象过
- 获取手机唯一标识 拼接的方式获取手机唯一标识第一种方式是获取IMEI,但是有的手机如果不是正品的话,就获取不到所以通过这一种方式还是会出现有
- Spring Boot除了可以打可执行jar包外,也支持传统的war包。本文介绍如何使用Spring Boot构建传统war包。Spring
- 在C语言中,想要获取字符串长度可以有很多方法,下面分别介绍一、使用sizeof()运算符在C语言中,sizeof() 是长度的运算符,括号中
- 一些Java项目中在mybatis与spring整合中有MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接
- 目标:双向拖动的自定义View国际惯例先预览后实现我们要实现的就是一个段位样式的拖动条,用来做筛选条件用的,细心的朋友可能会发现微信设置里面
- 1.初衷是由于调用银行接口的批量处理接口时,每次最多只能处理500条数据,但是当数据总数为510条时。我又不想第一次调用处理500条,第二次
- 前言在数据结构算法设计中,或者一个方法的具体实现的时候,有一种方法叫做“递归”,这种方法在思想上并不是特别难,但是实现起来还是有一些需要注意
- 本文实例讲述了Android开发实现Files文件读取解析功能。分享给大家供大家参考,具体如下:package com.example.fi
- 先上效果图这个效果来自于三星S5的充电界面,当然有些细节差别,主要看思路.本文目的是技术交流,不要将效果直接运用于商业产品和项目.电池背景因
- 1、CS、BS架构定义CS(Client/Server):客户端----服务器结构。C/S结构在技术上很成熟,它的主要特点是交互性强、具有安
- /// <summary> /// 计算本周起始日期(礼拜一的日期) /// </summary&
- 使用java制作一款简单的扫雷游戏,供大家参考,具体内容如下import java.util.*;public class nephelok
- 1、什么是线程及线程池线程是操作系统进行时序调度的基本单元。线程池可以理解为一个存在线程的池子,就是一个容器,这个容器只能存在线程。这个容器
- 本文实例讲述了Java编程实现判断网上邻居文件是否存在的方法。分享给大家供大家参考,具体如下:由于java不支持通过//192.168.19
- Flutter 键值存储数据库键值存储是开发中十分常见的需求,在Flutter开发中,一般使用 shared_preferences 插件来
- SingleClick:@Retention(AnnotationRetention.RUNTIME)@Target(AnnotationT