根据元素某个字段对比两个集合差集-交集-补集_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

智能推荐

使用jquery动态加载js,css文件_双十二的博客-程序员宅基地

$.extend({ includePath: '', include: function(file) { var files = typeof file == "string" ? [file]:file; for (var i = 0; i < files.length; i++) { var name = files

卷积神经网络和迁移学习的pytorch实现_ajiujiujiu的博客-程序员宅基地

卷积神经网络和迁移学习1 查看和下载常见CNN预训练模型的方法(AlexNet、GooLeNet、DenseNet、VGG、ResNet、NASNet、MobileNet、SqueezeNet等)(1)使用torchvisionimport torchvision.models as modelsalexnet = models.alexnet(num_classes=1000, pretrained=True) print(alexnet) (2)使用pytorch hubresne

Ios cocoapods 安装及使用_chengqiao5072的博客-程序员宅基地

更新ruby1.安装 rvmRVM:Ruby Version Manager,Ruby版本管理器,包括Ruby的版本管理和Gem库管理(gemset)1.安装rvmcurl -L get.rvm.io | bash -s stable 2. sour...

Uboot_for_Tiny6410_移植步骤详解_tiny6410 nboot_lsnail的博客-程序员宅基地

一、 设计要求1. 目的1) 掌握U-boot剪裁编写2) 掌握交叉编译环境的配置3) 掌握U-boot的移植2. 实现的功能1) U-boot编译成功2) 移植U-boot,使系统支持从NAND FLASH启动二、 _tiny6410 nboot

supervisor启动的程序读不到环境变量_supervisor 找不到环境_大城小事012的博客-程序员宅基地

现象在.bash_aliases里配置了环境变量,在命令行运行程序可以读取到,用supervisor启动的程序却读不到。处理用supervisor启动程序,环境变量需要写到supervisor的配置文件中。假定要用supervisor启动的程序对应的配置文件是/etc/supervisor/conf.d/service.conf。那么,在这个配置文件中需要用environment字段配置环境变量。例如:[program:service]command=java -jar /home/ub_supervisor 找不到环境

山东省第五届蓝桥杯 ///标题:啤酒和饮料//c/c++组_Strive_Buff的博客-程序员宅基地

标题:啤酒和饮料 啤酒每罐2.3元,饮料每罐1.9元。小明买了若干啤酒和饮料,一共花了82.3元。 我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐啤酒。 注意:答案是一个整数。请通过浏览器提交答案。 不要书写任何多余的内容(例如:写了饮料的数量,添加说明文字等)。______________________

随便推点

腾讯面试题 你了解ReentrantLock吗?-程序员宅基地

腾讯面试题 你了解ReentrantLock吗?ReetrantLock是一个可重入的独占锁,主要有两个特性,一个是支持公平锁和非公平锁,一个是可重入。ReetrantLock实现依赖于AQS(AbstractQueuedSynchronizer)(不懂得话可以看我上篇博客)。ReetrantLock主要依靠AQS维护一个阻塞队列,多个线程对加锁时,失败则会进入阻塞队列。等待唤醒,重新尝试加...

详解MegatronLM Tensor模型并行训练(Tensor Parallel)_MLTalks的博客-程序员宅基地

`MegatronLM`的第一篇论文Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism是2020年出的,针对billion级别的模型进行训练,例如具有38亿参数的类GPT-2的transformer模型和具有39亿参数的BERT模型.。

VirtualBox加载.vhd文件_weixin_30883311的博客-程序员宅基地

[转]1."新建" 虚拟电脑, 主硬盘选取现有的.vhd文件2.虚拟硬盘预设是挂载在[SATA控制器]下, 这时候不能成功启动Windows * ,首先点击[设定]按钮, 在[存储]里选中Windows *.vhd,进行删除,然后点击[IDE控制器]后的'加号',添加硬盘里的.vhd文件,启动即可成功转载于:https://www.cnblogs.com/mrsong/archive/2...

Android NoteX Q10:色值上的各个位代表什么?_"<?xml version=\"1.0\" encoding=\"utf-8\"?><chatbg_ganshenml的博客-程序员宅基地

一 前言自定义阴影时需要加上透明度才能更好实现平滑的效果,所以需要了解相关方面的知识。当然也不仅限于阴影实现效果,还有其他的UI设计也涉及到透明度了。二 色值代表ARGB这是对应的色值符号,A代表alpha透明度。 <!--100% —FF--> <!--95% — F2--> <!--90% — E6--> <!--85% — D9--> <!--80% — CC--> &_"

android 快速开发三、 获取应用的crash信息_岁月老王的博客-程序员宅基地

当用户发生了crash,开发者却无法得知程序为何crash,即便开发人员想去解决这个crash,但是由于无法知道用户当时crash信息,所以往往无能为力。android 提供了获取crash信息的方法。话不多说,直接上代码。package com.example.wmk.utils;import android.content.Context;import android.conte

Windows 缓冲区溢出与数据执行保护DEP_MoreWindows的博客-程序员宅基地

缓冲区溢出与数据执行保护DEP介绍先看一个缓冲区溢出的C++实例程序,代码如下(VC6.0下编译通过)://by MoreWindows #include #include #include #include #include void foo(const char *input){ char buf[4]; //buf 占4字节,后4字节为ebp,再后4个字节为返回地址。

推荐文章

热门文章

相关标签