List对象集合根据组合属性进行差集运算
背景
当List是一个基本数据类型的集合的时候,进行集合运算还比较方便,但是有这么一些业务场景,比如某个用户权限变化的列表,或者取数据的变化结果,当时有时候用笨方法多循环两次也是可以的,只不过代码显得比较复杂,而且性能也不会太好。这次迭代我也就遇到这么一个需求。
实现
场景:我们系统用户是四个维度这样的数据,我们需要保存这样的数据,提供给前端一个这样的接口,前端传递用户相应的数据(用户组|职位|部门|用户),但是前端不会告诉我们,哪些是新增的,哪些是删除的,还有哪些没有变化,反正数据一股脑的给你,后端来自己组织。当然,一般第一想法都是循环嘛,但是我一般的习惯都是将这种处理方法放在最后一个备选,实在想不出来好的方式才会使用最简单粗暴的方式哈哈哈。而且这个地方是要根据实体类里面的两个字段一起判断,无形中增加复杂度。List可以这样求差集(交并集类似):
// 差集
List<String> subList = list1.stream().filter(item -> list2.contains(item)).collect(toList());
但这个List就一个String类型的,方便,而我们要判断的是两个对象是不是相等,简单嘛,一样这样使用嘛,那万一两个对象并不相同的,比如一个列表是从数据库中取出来的值,一个传出来的,它们的字段值都不同,那他们equals肯定也不同的,过滤后的值也不同,就会造成数据错误。
// 考虑过滤数据,不进行重复更新
List<SaveLibUserParam> saveLibUserParamList = param.getSaveLibUserParamList();
List<UserCourseLibraryManage> originSaveList = Lists.newArrayList();
if (Objects.nonNull(saveLibUserParamList) && saveLibUserParamList.size() > 0) {
originSaveList = BeanConvertUtils.convertList(saveLibUserParamList, UserCourseLibraryManage.class);
}
// 查询出本来的旧数据
List<UserCourseLibraryManage> list = userCourseLibraryManageDao.queryListByCompanyId(companyId);
log.info("originList:{}", originSaveList);
log.info("list:{}", list);
// 需要本次新增的,即在origin中而list没有的
// 需要本次删除的,即在origin没有而list中有的
List<UserCourseLibraryManage> needAddList = originSaveList.stream().filter(item -> !list.contains(item)).collect(Collectors.toList());
List<UserCourseLibraryManage> finalOriginSaveList = originSaveList;
List<UserCourseLibraryManage> deleteList = list.stream().filter(item -> !finalOriginSaveList.contains(item)).collect(Collectors.toList());
log.info("needAddList:size:{}, data:{}", needAddList.size(), needAddList);
log.info("deleteList:size:{}, data:{}", deleteList.size(), deleteList);
所以要考虑判断两个对象相等的条件,这里大家应该都知道了,就是重写equals方法,判断对象中值相等用equals方法,不用用\(==\)符号,\(==\)符号在判断对象类型时判断的是地址,这个地方需要注意的。对上面的UserCourseLibraryManage实体对象进行重写equals,在重写equals的时候,一定要注意:hashCode一般也建议重写,以保证两个对象的hash值一致,只有当对象的hash值一致时,系统才会判定这两个对象相等。重写hashcode的时候为什么用17,网上说好像Jdk就用的17,还有待考证,反正保证不要超出int范围就可以。
/**
* 重写equals方法
* @param obj
* @return
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof UserCourseLibraryManage) {
if (Objects.equals(((UserCourseLibraryManage) obj).dataType, this.dataType)
&& Objects.equals(((UserCourseLibraryManage) obj).dataId, this.dataId)) {
// System.out.println("相同对象:obj:"+obj+", this:{}"+this+"");
return true;
} else {
return false;
}
} else {
return super.equals(obj);
}
}
/**
* 重写hashcode
* @return
*/
@Override
public int hashCode() {
int newHashCode = dataType.hashCode();
newHashCode = 17 * newHashCode + dataId.hashCode();
return newHashCode;
}
这样处理了一番过后,过滤处理后的数据就是我们想要的数据,达到了目的,并且性能也肯定得到了提升,使用的java8的流处理。
tips:上面list.stream处理的地方求差集用list自己的removeAll也是可以的。有兴趣的可以看下源码,但removeAll会将原数据集合改变。
希望以后如果有小伙伴遇到这种问题,刚好不太了解如何处理,希望这个分享能有一定的帮助!
List对象集合根据组合属性进行差集运算的更多相关文章
- C# List 集合 交集、并集、差集、去重, 对象集合、 对象、引用类型、交并差补、List<T>
关键词:C# List 集合 交集.并集.差集.去重, 对象集合. 对象.引用类型.交并差.List<T> 有时候看官网文档是最高效的学习方式! 一.简单集合 Intersect 交集, ...
- C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询
1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法 ...
- C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数
一.隐式类型var 从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,编译器自动推断类型. 1.var类型的局部变量必须赋予初始值,包括匿名 ...
- Java List对象集合按对象属性分组、分组汇总、过滤等操作示例
import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Col ...
- Stream流用于按照对象中某一属性来对集合去重+简单数据类型集合的去重
上次对Stream流来进行分组的文章很多人看,想看的可以来这: Stream流来进行集合分组 这次小编又带来Stream的去重,话不多数,直接上代码: 这是对简单数据类型的去重 //字符串集合进行简单 ...
- 如何将List集合中相同属性的对象合并
在实际的业务处理中,我们经常会碰到需要合并同一个集合内相同属性对象的情况,比如,同一个用户短时间内下的订单,我们需要将各个订单的金额合并成一个总金额.那么用lambda表达式和HashMap怎么分别处 ...
- 再谈使用Emit把Datatable转换为对象集合(List<T>)
一.前因和存在的问题 前面我写了一篇<使用Emit把Datatable转换为对象集合(List<T>)>的博文,其实起源于我自己编写的一个orm工具(见前面几篇博文有介绍),里 ...
- 深入理解javascript对象系列第二篇——属性操作
× 目录 [1]查询 [2]设置 [3]删除[4]继承 前面的话 对于对象来说,属性操作是绕不开的话题.类似于“增删改查”的基本操作,属性操作分为属性查询.属性设置.属性删除,还包括属性继承.本文是对 ...
- SQL中对于两个不同的表中的属性取差集except运算
SQL中对两个集合取差集运算,使用except关键字,语法格式如下: SELECT column_name(s) FROM table_name1 EXCEPT SELECT column_name( ...
随机推荐
- 使用pdf.js aspose各种文档转PDF 版本对应license.xml 去水印破解
在使用pdf.js途中,使用aspose转换的文件一直有水印,在网上找了许多破解办法都是已经失效的,于是乎,就查看了一下jar的源码,找到了版本对应的破解字符(如下):对应版本为 aspose-wor ...
- 配置NFS实现nginx动静分离
案例子任务一.安装配置NFS服务器 步骤1:使用docker容器配置NFS服务器 启动centos容器并进入 docker run -d --privileged centos:v1 /usr/sbi ...
- Java生成窗口
//字符串数组转变成int数组ints[i] = Integer.parseInt(str_string[i]);//设置窗口关闭Frame.addWindowListener(new WindowA ...
- 解决threadLocal父子变量传递问题
一.问题的提出 在系统开发过程中常使用ThreadLocal进行传递日志的RequestId,由此来获取整条请求链路.然而当线程中开启了其他的线程,此时ThreadLocal里面的数据将会出现无法获取 ...
- Mono for android 访问Webservice和WebApi以及获取和解析JSON
先看效果,注意:(1)这里由于我的模拟器不支持中文输入,所以,对于这张效果图,我是直接在代码中写死了我的查询城市,在下面的代码中我是没有把要查询的城市写死的. (2)读者要想成功使用本示例的所有代码的 ...
- 【分布式锁的演化】“超卖场景”,MySQL分布式锁篇
前言 之前的文章中通过电商场景中秒杀的例子和大家分享了单体架构中锁的使用方式,但是现在很多应用系统都是相当庞大的,很多应用系统都是微服务的架构体系,那么在这种跨jvm的场景下,我们又该如何去解决并发. ...
- ubutu14.04选中文本就会删除问题解决
1.网上解法 (1)重装ibus sudo apt-get install --reinstall ibus (2)键盘格局为english(united state) (3)升级火狐为最新版 以上方 ...
- ssh 免密设置
在master中生成dsa: ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa cat ~/.ssh/id_dsa.pub >> ~/.ssh/author ...
- 项目实战--Stream流实现字符串拼接
需求说明 概述:前端页面查询列表中有个"二级类目"的多选下拉框,用户选择二级类目后,需要从后台数据库查询条件内的数据. 目标:将前端页面传入后端的字符串例如"女性护理, ...
- 意想不到,这个神奇的bug让我加班到深夜
给大家分享一个近期解决的线上问题,起因是这样的,近期参与公司的一个项目,工程量很大,代码编写测试过后终于到了紧张的上线时刻. 项目上线 上线前照例忐忑不安了一番,因为工程量比较大,预估可能不会很顺利, ...