根据元素某个字段对比两个集合差集-交集-补集

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
public class CompareListUtil {

    /**
     * 差集key-add
     */
    public static String DIFFERENCE = "difference_add";

    /**
     * 交集key-update
     */
    public static String INTERSECTION = "intersection_update";

    /**
     * 补集key-delete
     */
    public static String COMPLEMENT = "complement_delete";

    /**
     * 根据某个字段对比两个集合
     *
     * @param oldList   旧的集合
     * @param newList   新的集合
     * @param fieldName 需要对比的字段名称
     * @return 差集key-add 交集key-update 补集key-delete
     * @throws
     */
    public static <T> Map<String, List<T>> compareList(List<T> oldList, List<T> newList, String fieldName) throws IllegalAccessException {
        if (StringUtils.isBlank(fieldName)) {
            throw new RuntimeException("\n对比字段不能为空");
        }
        // 空集合
        List<T> emptyList = Lists.newArrayList();
        List<T> differenceList = Lists.newArrayList();
        List<T> intersectionList = Lists.newArrayList();
        List<T> complementList = Lists.newArrayList();
        Map<String, List<T>> resultMap = Maps.newHashMap();
        if (CollectionUtils.isEmpty(oldList)) {
            resultMap.put(DIFFERENCE, newList);
            resultMap.put(INTERSECTION, emptyList);
            resultMap.put(COMPLEMENT, emptyList);
            return resultMap;
        }
        if (CollectionUtils.isEmpty(newList)) {
            resultMap.put(DIFFERENCE, emptyList);
            resultMap.put(DIFFERENCE, emptyList);
            resultMap.put(COMPLEMENT, oldList);
            return resultMap;
        }

        Set<Object> existSet = Sets.newHashSet();
        for (T old : oldList) {
            Object fieldValue = getFieldValue(old, fieldName);
            existSet.add(fieldValue);
        }
        Set<Object> newSet = Sets.newHashSet();
        for (T newObj : newList) {
            Object fieldValue = getFieldValue(newObj, fieldName);
            newSet.add(fieldValue);
        }

        for (T newObj : newList) {
            Object fieldValueNew = getFieldValue(newObj, fieldName);
            if (existSet.contains(fieldValueNew)) {
                intersectionList.add(newObj);
            } else {
                differenceList.add(newObj);
            }
        }

        for (T old : oldList) {
            Object fieldValueNew = getFieldValue(old, fieldName);
            if (!newSet.contains(fieldValueNew)) {
                complementList.add(old);
            }
        }
        resultMap.put(DIFFERENCE, differenceList);
        resultMap.put(INTERSECTION, intersectionList);
        resultMap.put(COMPLEMENT, complementList);
        return resultMap;
    }

    /**
     * 获取元素T中的字段值
     *
     * @param t         元素
     * @param fieldName 字段名称
     * @return
     * @throws IllegalAccessException
     */
    private static <T> Object getFieldValue(T t, String fieldName) throws IllegalAccessException {
        Field targetField = Arrays.stream(t.getClass().getDeclaredFields())
                .filter(field -> field.getName().equals(fieldName)).collect(Collectors.toList()).get(0);
        targetField.setAccessible(true);
        return targetField.get(t);
    }

    public static void main(String[] args) throws IllegalAccessException {
        List<User> usersOld = Lists.newArrayList();
        usersOld.add(new User(1L, "1"));
        usersOld.add(new User(2L, "1"));
        usersOld.add(new User(3L, "1"));
        usersOld.add(new User(4L, "1"));

        List<User> usersNew = Lists.newArrayList();
        usersNew.add(new User(1L, "1"));
        usersNew.add(new User(2L, "1"));
        // usersNew.add(new User(3L, "1"));
        usersNew.add(new User(4L, "1"));
        usersNew.add(new User(5L, "1"));
        Map<String, List<User>> maps = compareList(usersOld, usersNew, "userId");

        maps.forEach((k, v) -> {
            log.info("\n {} : {}", k, JSONObject.toJSONString(v));
        });
    }

}

@Data
@AllArgsConstructor
class User {
    private Long userId;
    private String userName;
}
intersection_update : [{"userId":1,"userName":"1"},{"userId":2,"userName":"1"},{"userId":4,"userName":"1"}]
19:51:18.653 [main] INFO com.enterprise.common.util.tool.CompareListUtil - 
difference_add : [{"userId":5,"userName":"1"}]
19:51:18.653 [main] INFO com.enterprise.common.util.tool.CompareListUtil - 
complement_delete : [{"userId":3,"userName":"1"}]

JDK8-交集-差集

// 交集
List<User> intersectA = usersOld
        .stream() //获取第一个集合的Stream1
        .filter(  //取出Stream1中符合条件的元素组成新的Stream2,lambda表达式1返回值为true时为符合条件
                a ->  //lambda表达式1,a为lambda表达式1的参数,是Stream1中的每个元素
                        usersNew.stream() //获取第二个集合的Stream3
                                .map(User::getUserId) //将第二个集合每个元素的id属性取出来,映射成新的一个Stream4
                                .anyMatch( //返回值(boolean):Stream4中是否至少有一个元素使lambda表达式2返回值为true
                                        id -> //lambda表达式2,id为lambda表达式2的参数,是Stream4中的每个元素
                                                Objects.equals(a.getUserId(), id) //判断id的值是否相等
                                )
        )
        .collect(Collectors.toList()); //将Stream2转换为List
log.info("\nintersectA {}", JSONObject.toJSONString(intersectA));


// 差集
List<User> differenceB = usersNew.stream().filter(b -> usersOld.stream().map(User::getUserId).noneMatch(id ->
        Objects.equals(b.getUserId(), id))).collect(Collectors.toList());
log.info("\ndifference {}", JSONObject.toJSONString(differenceB));
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gzh-程序员灿灿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值