根据对象中某字段判断两个List数据,哪些需要新增,删除,修改

本文介绍了一种使用Hutool库进行数据对比的方法,演示了如何在新旧数据中找出差异,包括插入、更新和删除操作。但强调在大数据情况下反射方法效率较低,建议采用更高效策略。实验对比了反射与不使用反射的性能差异。
摘要由CSDN通过智能技术生成

可用于数据对接时,筛选出新旧数据中有差异的对象;此方法需要引入HUTOOL工具

		<!--Hutool是一个小而全的Java工具类库-->
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.7.16</version>
		</dependency>

 此方法只是用于思路展示;
 大数据情况下,建议不要使用此反射方法,直接复制思路,替换list,快很多;不要问为什么,问就是反射;
 附带用20000条数据下反射与不用的对比耗时

package com.ambition.hisLink.utils;

import cn.hutool.core.builder.EqualsBuilder;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ListCompareUtils {
    /**
     *
     *  (此方法只是用于思路展示;
     *  大数据情况下,建议不要使用此方法,直接复制思路,替换list,快很多;有大量反射;
     *  附带用大量反射与少用的对比耗时)
     *
     * 两个List比较;新数据与旧数据进行对比,旧数据与新数据中通过指定唯一字段值进行比对,判断旧数据其他字段中哪些需要修改;
     *                  以及新数据中哪些为新增数据,旧数据哪些需要删除
     * @param newData 新数据
     * @param oldData 旧数据
     * @param notCompare 不需要判断修改的字段名(null时,判断所有字段)
     * @param only    新旧数据比对的字段名(唯一字段值所在字段)
     * @param <T>
     * @return
     */
    public static <T> Map<String, List<T>> getListCompare(List<T> newData, List<T> oldData, String[] notCompare, String[] only) {
        Map<String, List<T>> map = new HashMap();
        List<T> updateList = new ArrayList<>();
        for (int i = newData.size()-1; i >=0 ; i--) {
            for (int j = oldData.size()-1; j >=0 ; j--) {
                T t = newData.get(i);
                T t1 = oldData.get(j);
                if (judgeOnly(only, t, t1)) {
                    if (!EqualsBuilder.reflectionEquals(t,t1,notCompare)) {
                        //当有修改时,加入updateList中,跳出旧oldData,继续遍历newData;
                        updateList.add(t);
                    }
                    newData.remove(i);
                    oldData.remove(j);
                    break;
                }
            }
        }
        log.info("insertList ->{},updateList ->{},deleteList->{}",newData.size(),updateList.size(),oldData.size());
        map.put("insertList", newData);
        map.put("updateList", updateList);
        map.put("deleteList", oldData);
        return map;
    }

    /**
     * 判断是否满足比较条件
     *
     * @param only 需要满足相等的字段名
     * @param one  对象1
     * @param two  对象2
     * @param <T>
     * @return
     */
    private static <T> boolean judgeOnly(String[] only, T one, T two) {
        for (String onlyStr : only) {
            Object onlyValue = ReflectUtil.getFieldValue(one, onlyStr);
            Object onlyValue1 = ReflectUtil.getFieldValue(two, onlyStr);
            if ((!ObjectUtil.isBasicType(onlyValue) && !(onlyValue instanceof String)  )
                    || (!ObjectUtil.isBasicType(onlyValue1) && !(onlyValue1 instanceof String)  )
                    || !ObjectUtil.equal(onlyValue, onlyValue1)) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        List<DemoPojo> value1 = new ArrayList<>();
        List<DemoPojo> value2 = new ArrayList<>();
        for (int i = 0; i < 20000; i++) {
            DemoPojo pdaExecutionDrug = new DemoPojo();
            pdaExecutionDrug.setBedno(i + "");
            pdaExecutionDrug.setPatname("zhangshan"+i);
            pdaExecutionDrug.setCureno("1234");
            value1.add(pdaExecutionDrug);
        }

        for (int i = 2; i < 25000; i++) {
            DemoPojo pdaExecutionDrug = new DemoPojo();
            pdaExecutionDrug.setBedno(i + "");
            pdaExecutionDrug.setPatname("zhangshan"+(i<15000?i : i+1));
            pdaExecutionDrug.setCureno( "123");
            value2.add(pdaExecutionDrug);
        }
        StopWatch stopWatch = DateUtil.createStopWatch();
        stopWatch.start("用反射");
        Map<String, List<DemoPojo>> listCompare = getListCompare(CollUtil.newArrayList(value1), CollUtil.newArrayList(value2), null, new String[]{"bedno"});
        stopWatch.stop();
        stopWatch.start("不用反射");
        List<DemoPojo> update = new ArrayList<>();
        for (int i = value1.size()-1; i >=0 ; i--) {
            for (int j = value2.size()-1; j >=0 ; j--) {
                DemoPojo t = value1.get(i);
                DemoPojo t1 = value2.get(j);
                if (t.getBedno().equals(t1.getBedno())) {
                    if (!EqualsBuilder.reflectionEquals(t,t1,"bedNo","cureno")){
                        update.add(t);
                    }
                    value1.remove(i);
                    value2.remove(j);
                    break;
                    }

                }
            }
        log.info("insertList ->{},updateList ->{},deleteList->{}",value1.size(),update.size(),value2.size());
        stopWatch.stop();
        Console.log(stopWatch.prettyPrint(TimeUnit.SECONDS));

    }

}
@Data
 class DemoPojo {
    private String bedno;
    private String patname;
    private String cureno;

 }
2022-03-10 15:04:55.458  INFO   --- [           main] c.a.hisLink.utils.ListCompareUtils       : insertList ->2,updateList ->19998,deleteList->5000
2022-03-10 15:04:56.453  INFO   --- [           main] c.a.hisLink.utils.ListCompareUtils       : insertList ->2,updateList ->5000,deleteList->5000
StopWatch '': running time = 12 s
---------------------------------------------
s         %     Task name
---------------------------------------------
000000011  92%   用反射
000000000  08%   不用反射

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值