1.业务背景
- 在日常开发中,有时会遇到需要对比两个集合来计算出两个集合的交集、差集。以此来决定之后对数据库的
insert、delete、update
操作。例如,在一些管理系统中配置管理员列表后,如果需要更新管理员列表,需要从前端获取新管理员列表,比对数据库中旧有的管理员列表,然后决定哪些集合需要insert入数据库,哪些需要从数据库中delete。
- 以上是业务背景的简单介绍,但是如果是一些数据规模比较小或者修改不是很频繁的业务场景,则不需要比对集合,完全可以将旧有数据全部删除,然后将新数据insert入库中。
2.工具类介绍
2.1 主工具类
package cn.sun.utils;
import org.springframework.util.CollectionUtils;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author : ssk
* @date : 2020/11/22
*
* @desc 集合比对
*/
public class CollectionCompareUtil {
/**
* 比对新老集
*
* @param oldTargetList 旧有集合——一般从数据库中查出来
* @param newTargetList 新集合—— 一般根据前端数据组装
* @param compareSelection 比对标识:需要比对两个结合的交集、差集选项。默认全为true,置为true表示需要计算该类型。详见CompareFlag描述
* @param <T> 传入T需按需重写equal()、hashCode()方法
* @return
*/
public static <T> CollectionCompareResult compare(List<T> oldTargetList, List<T> newTargetList, CompareSelection compareSelection) {
if (CollectionUtils.isEmpty(oldTargetList) || CollectionUtils.isEmpty(newTargetList)) {
throw new RuntimeException("入参错误");
}
// 自身去重
Set<T> oleTargetSet = new HashSet<>(oldTargetList);
Set<T> newTargetSet = new HashSet<>(newTargetList);
CollectionCompareResult collectionCompareResult = new CollectionCompareResult();
// 需更新
if (compareSelection.getUpdateFlag()) {
collectionCompareResult.setUpdateTargetList(oleTargetSet.stream().filter(newTargetSet::contains).collect(Collectors.toList()));
}
// 需新增
if (compareSelection.getAddFlag()) {
collectionCompareResult.setAddTargetList(newTargetSet.stream().filter(item -> !oleTargetSet.contains(item)).collect(Collectors.toList()));
}
// 需删除
if (compareSelection.getDeleteFlag()) {
collectionCompareResult.setDeleteTargetList(oleTargetSet.stream().filter(item -> !newTargetSet.contains(item)).collect(Collectors.toList()));
}
return collectionCompareResult;
}
}
- 对需要比对的实体按需重写
equal()和hashCode()
方法
package cn.sun.test.bean;
import lombok.Builder;
import lombok.Data;
import java.util.Objects;
/**
* @author : ssk
* @date : 2020/11/22
*/
@Data
@Builder
public class User {
private String id;
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(id, user.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
2.2 需比对类型封装
package cn.sun.utils;
/**
* @author : ssk
* @date : 2020/11/22
*
* 对两个集合交集,差集选择
*/
public class CompareSelection {
/**
* 差集(newList-oldList)标识
*/
private Boolean addFlag = true;
/**
* 交集(newList:oldList)标识
*/
private Boolean updateFlag = true;
/**
* 差集(oldList-newList)标识
*/
private Boolean deleteFlag = true;
public Boolean getAddFlag() {
return addFlag;
}
public void setAddFlag(Boolean addFlag) {
this.addFlag = addFlag;
}
public Boolean getUpdateFlag() {
return updateFlag;
}
public void setUpdateFlag(Boolean updateFlag) {
this.updateFlag = updateFlag;
}
public Boolean getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(Boolean deleteFlag) {
this.deleteFlag = deleteFlag;
}
}
2.3 比对结果封装
package cn.sun.utils;
import java.util.List;
/**
* @author : ssk
* @date : 2020/11/22
*/
public class CollectionCompareResult<T> {
/**
* 需新增列表
*/
private List<T> addTargetList;
/**
* 需删除列表
*/
private List<T> deleteTargetList;
/**
* 需更新列表
*/
private List<T> updateTargetList;
public List<T> getAddTargetList() {
return addTargetList;
}
public void setAddTargetList(List<T> addTargetList) {
this.addTargetList = addTargetList;
}
public List<T> getDeleteTargetList() {
return deleteTargetList;
}
public void setDeleteTargetList(List<T> deleteTargetList) {
this.deleteTargetList = deleteTargetList;
}
public List<T> getUpdateTargetList() {
return updateTargetList;
}
public void setUpdateTargetList(List<T> updateTargetList) {
this.updateTargetList = updateTargetList;
}
}
2.4 简单总结
- 使用该工具类需要注意以下几点:
- 按需重写集合中实体的
equal()、hashCode()
两个方法
- 按需定义CompareSelection。如果没有定义则默认计算三种类型。
3.工具类简单测试
package cn.sun.test.utils;
import cn.sun.test.bean.User;
import cn.sun.utils.CollectionCompareResult;
import cn.sun.utils.CollectionCompareUtil;
import cn.sun.utils.CompareSelection;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* @author : ssk
* @date : 2020/11/22
*/
public class CollectionCompareUtilTest {
@Test
public void test() {
User user1 = User.builder().id("1").name("赤犬").build();
User user2 = User.builder().id("2").name("青雉").build();
User user3 = User.builder().id("3").name("黄猿").build();
User user4 = User.builder().id("4").name("藤虎").build();
User user5 = User.builder().id("5").name("绿牛").build();
List<User> oldTargetList = new ArrayList<>();
oldTargetList.add(user1);
oldTargetList.add(user2);
oldTargetList.add(user3);
List<User> newTargetList = new ArrayList<>();
newTargetList.add(user3);
newTargetList.add(user4);
newTargetList.add(user5);
CollectionCompareResult compareResult = CollectionCompareUtil.compare(oldTargetList, newTargetList, new CompareSelection());
System.out.println("海军大将变动---未变动大将:" + compareResult.getUpdateTargetList()
+ "离职大将:" + compareResult.getDeleteTargetList()
+ "新上任大将:" + compareResult.getAddTargetList());
}
}
海军大将变动---未变动大将:[User(id=3, name=黄猿)]
离职大将:[User(id=1, name=赤犬), User(id=2, name=青雉)]
新上任大将:[User(id=4, name=藤虎), User(id=5, name=绿牛)]