集合交集、差集工具类

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());
    }
}

  • output:
海军大将变动---未变动大将:[User(id=3, name=黄猿)]
  离职大将:[User(id=1, name=赤犬), User(id=2, name=青雉)]
  新上任大将:[User(id=4, name=藤虎), User(id=5, name=绿牛)]

posted @ 2020-11-22 21:39  rider_add  阅读(626)  评论(0编辑  收藏  举报