根据元素某个字段对比两个集合差集-交集-补集_jsonobject取差集_gzh-程序员灿灿的博客-程序员宅基地

技术标签: 工具类  java  

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));
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010106375/article/details/120516198

智能推荐

JS使用new创建对象与不使用new创建对象的区别_js 中有的类为什么不用new-程序员宅基地

本文将探讨一下使用new创建对象与不使用new创建对象的区别,一下面这段代码为例: function Person(name){ this.name = name; console.log(this); return {name:name};//返回对象}Person.prototype.name = "Alice";var person1 = new Person("B..._js 中有的类为什么不用new

DirectX12(D3D12)基础教程(七)——渲染到纹理、正交投影、UI渲染基础_d3d12 教程-程序员宅基地

目录 1、前言2、渲染到纹理3、调试支持4、正交投影5、UI渲染基础6、本章完整代码链接1、前言记得那是在差不多10多年前,我在工作中认识了一位好兄弟小杨。那时他刚毕业,跟我是同一所大学,算我的校友。彼时,我已工作快10年了,在当时那家不大的软件公司管VC++研发部。小杨加入了我的团队。他长了个圆脸,跟我一样戴副眼镜,话语不多,而且眼睛中并没有闪烁着我希望看到的..._d3d12 教程

生成字典序排列(C++ STL) next_permutation函数_c++ stl中求字字典序-程序员宅基地

生成下一个字典序排列#include bool next_permutation( iterator start, iterator end );The next_permutation() function attempts to transform the given range of elements [start,end) intothe next_c++ stl中求字字典序

Python中range和xrange的区别_for i in xrange(0, 10)-程序员宅基地

这两个基本上都是在循环的时候用。In [1]: for i in range(0,10): ...: print i ...: 0123456789In [2]: for i in xrange(0,10): print i ...: 0123456789这两个输出的结果都是一样的,实际上有很多不_for i in xrange(0, 10)

spring boot引入starter-jdbc报错 java.lang.NoClassDefFoundError: org/slf4j/helpers/ThreadLocalMapOfStacks_北·迁~的博客-程序员宅基地

问题说找不到helpers下的ThreadLocalMapOfStacks类,我看了一下这个slf4j下的确没有这个类

java前端如何播放rtsp流_前端怎么播放RTMP、RTSP、HTTP协议 的流媒体资源?-程序员宅基地

关于播放rtmp http 协议的流媒体资源,最后采用的video.js来进行播放的http的 依赖 videojs-contrib-hls 和video.jstype="application/x-mpegURL">js文件var player = videojs('example-video');player.play();rtmp的依赖 video.js videojs-fla..._java+vue播放rtsp

随便推点

Linux上配置Jupyter Notebook远程访问(docker)_linux 查看 docker jupyternotebook 地址-程序员宅基地

Linux上配置Jupyter Notebook远程访问1. 安装ipython, jupyter2. 生成配置文件3. 生成密码4. 修改默认配置文件5.启动jupyter notebook6. 在浏览器中查看7、注意阿里云服务器的安全组配置本身自己机器上安装了太多东西,有点慢,本来也喜欢所有的东西搬到服务上,所以如果能安装一个远程的Jupyter 服务器,用起来就会很方便。记录下自己的安装步骤1. 安装ipython, jupyterpip install ipython pip insta_linux 查看 docker jupyternotebook 地址

Asp.netCore 3.1学习:C#除去list中重复元素的方法_asp.netcore list 交集-程序员宅基地

开发中,经常遇到List<obj>去重的问题,最普通的做法就是用2层循环滤过去重,比如以下方法: if (req.Count > 1) { for (int i = 0; i < req.Count; i++) //外循环是循环的次数 { ..._asp.netcore list 交集

Web服务器——HTTP状态机解析-程序员宅基地

Web服务器——HTTP状态机解析程序说明主要练习HTTP解析的状态机的使用。接收一个客户端请求,判断是否是一个正确的GET请求,并解析出相应字段。运行方法编译g++ main.cpp -o main直接运行也可以,默认ip为127.0.0.1,默认端口为8888运行curl 127.0.0.1:7777/index.html运行结果:客户端发起请求:# 方式1:命令行..._http状态机

(笔记)NDK is missing a “platforms“ directory. If you are using NDK, verify the ndk.dir is set to a val_疼老婆会发达的博客-程序员宅基地

一、问题NDK is missing a "platforms" directory.If you are using NDK, verify the ndk.dir is set to a valid NDK directory. It is currently set to D:\AndroidStudioSDK\ndk-bundle.If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local

org.springframework.dao.DuplicateKeyException: a different object with the same identifier value....-程序员宅基地

org.springframework.dao.DuplicateKeyException: a different object with the same identifier value was already associated with the session: [com.phoneinfo.entity.Informations#10]; nested exception is org_org.springframework.dao.duplicatekeyexception: a different object with the s

GlusterFS基本部署-程序员宅基地

一、快速部署GlusterFS1.前期环境的准备因为做实验我用的是VMware ,最少准备3台虚拟机,2台用来做服务端,1台用来做客户端,服务端的配置(1C2G,硬盘最少2块),客户端(1C2G)本人用自己的机子,大家可以按照自己的实际情况来配置。首先我把两台服务端的虚拟机的主机名改成了node1,node2 接下来配hosts文件主机名会好记点。node1信息[root@no...

推荐文章

热门文章

相关标签