Java工具类:对比两个集合并返回差异

在实际的软件开发过程中,经常会遇到需要对比两个集合并找出它们之间的差异的情况。为了解决这个问题,我们可以编写一个Java工具类来完成这个任务。本文将介绍如何编写这样一个工具类,并提供详细的代码解释和使用示例。

问题描述

假设我们有两个集合,我们需要对比它们并找出它们之间的差异。我们希望能够找出集合1中存在但集合2中不存在的元素,以及集合2中存在但集合1中不存在的元素。

import java.util.*;

public class CollectionComparator {

    /**
     * 比较两个集合,返回包含不变、新增和删除元素的Map。
     *
     * @param list1  第一个集合
     * @param list2  第二个集合
     * @param fields 用于判断集合中元素是否一样的字段名
     * @param <T>    集合中元素的类型
     * @return 包含不变、新增和删除元素的Map
     */
    public static <T> Map<String, List<T>> compareCollections(List<T> list1, List<T> list2, String... fields) {
        // 创建结果Map
        Map<String, List<T>> result = new HashMap<>();
        // 计算新增、删除和不变的元素,并放入结果Map中
        result.put("新增", findAddedElements(list1, list2, fields));
        result.put("删除", findRemovedElements(list1, list2, fields));
        result.put("不变", findUnchangedElements(list1, list2, fields));
        return result;
    }

    /**
     * 查找新增的元素
     *
     * @param list1  第一个集合
     * @param list2  第二个集合
     * @param fields 用于判断集合中元素是否一样的字段名
     * @param <T>    集合中元素的类型
     * @return 新增的元素列表
     */
    private static <T> List<T> findAddedElements(List<T> list1, List<T> list2, String[] fields) {
        return findDifference(list2, list1, fields);
    }

    /**
     * 查找删除的元素
     *
     * @param list1  第一个集合
     * @param list2  第二个集合
     * @param fields 用于判断集合中元素是否一样的字段名
     * @param <T>    集合中元素的类型
     * @return 删除的元素列表
     */
    private static <T> List<T> findRemovedElements(List<T> list1, List<T> list2, String[] fields) {
        return findDifference(list1, list2, fields);
    }

    /**
     * 查找不变的元素
     *
     * @param list1  第一个集合
     * @param list2  第二个集合
     * @param fields 用于判断集合中元素是否一样的字段名
     * @param <T>    集合中元素的类型
     * @return 不变的元素列表
     */
    private static <T> List<T> findUnchangedElements(List<T> list1, List<T> list2, String[] fields) {
        // 创建字段集合
        Set<String> fieldSet = new HashSet<>(Arrays.asList(fields));
        // 创建不变的元素列表
        List<T> unchangedElements = new ArrayList<>();
        // 遍历第一个集合
        for (T obj1 : list1) {
            boolean found = false;
            // 遍历第二个集合
            for (T obj2 : list2) {
                // 判断两个对象是否相等
                if (areEqual(obj1, obj2, fieldSet)) {
                    found = true;
                    break;
                }
            }
            // 如果第一个集合中的元素在第二个集合中存在,则添加到不变的元素列表中
            if (found) {
                unchangedElements.add(obj1);
            }
        }
        return unchangedElements;
    }

    /**
     * 查找两个集合的差异
     *
     * @param list1  第一个集合
     * @param list2  第二个集合
     * @param fields 用于判断集合中元素是否一样的字段名
     * @param <T>    集合中元素的类型
     * @return 差异元素列表
     */
    private static <T> List<T> findDifference(List<T> list1, List<T> list2, String[] fields) {
        // 创建字段集合
        Set<String> fieldSet = new HashSet<>(Arrays.asList(fields));
        // 创建差异元素列表
        List<T> differenceList = new ArrayList<>();
        // 遍历第一个集合
        for (T obj1 : list1) {
            boolean found = false;
            // 遍历第二个集合
            for (T obj2 : list2) {
                // 判断两个对象是否相等
                if (areEqual(obj1, obj2, fieldSet)) {
                    found = true;
                    break;
                }
            }
            // 如果第一个集合中的元素在第二个集合中不存在,则添加到差异元素列表中
            if (!found) {
                differenceList.add(obj1);
            }
        }
        return differenceList;
    }

    /**
     * 比较两个对象是否相等
     *
     * @param obj1   对象1
     * @param obj2   对象2
     * @param fields 用于判断对象是否相等的字段集合
     * @param <T>    对象的类型
     * @return 如果对象相等则返回true,否则返回false
     */
    private static <T> boolean areEqual(T obj1, T obj2, Set<String> fields) {
        // 遍历字段集合
        for (String field : fields) {
            try {
                // 获取对象1中字段的值
                Object value1 = obj1.getClass().getField(field).get(obj1);
                // 获取对象2中字段的值
                Object value2 = obj2.getClass().getField(field).get(obj2);
                // 判断两个字段值是否相等
                if (!Objects.equals(value1, value2)) {
                    return false;
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                // 捕获异常并打印异常信息
                e.printStackTrace();
            }
        }
        // 如果所有字段值都相等,则返回true
        return true;
    }

    public static void main(String[] args) {
        // 测试示例
        List<Person> list1 = new ArrayList<>();
        list1.add(new Person("张三", 10));
        list1.add(new Person("张三2", 10));
        list1.add(new Person("张三3", 10));

        List<Person> list2 = new ArrayList<>();
        list2.add(new Person("张三", 10));
        list2.add(new Person("张三2", 10));
        list2.add(new Person("张三4", 10));

        Map<String, List<Person>> differenceMap = compareCollections(list1, list2, "name", "age");

        for (Map.Entry<String, List<Person>> entry : differenceMap.entrySet()) {
            System.out.println(entry.getKey() + "的元素:");
            for (Person person : entry.getValue()) {
                System.out.println(person);
            }
        }
    }

    static class Person {
        public String name;
        public int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
}

如果是private字段,使用下面的方法获取,需要加上getter/setter方法

private static <T> boolean areEqual(T obj1, T obj2, Set<String> fields) {
        // 遍历字段集合
        for (String field : fields) {
            try {
                
                String getMethodName = String.format("%s%s%s", "get", field.substring(0, 1).toUpperCase(), field.substring(1));

                Method newMethod1 = obj1.getClass().getDeclaredMethod(getMethodName);
                // 获取对象1中字段的值
                Object value1 = newMethod1.invoke(obj1);
                Method newMethod2 = obj2.getClass().getDeclaredMethod(getMethodName);
                //获取对象2中字段的值
                Object value2 = newMethod2.invoke(obj2);
                // 判断两个字段值是否相等
                if (!Objects.equals(value1, value2)) {
                    return false;
                }
            } catch (IllegalAccessException |InvocationTargetException | NoSuchMethodException e) {
                // 捕获异常并打印异常信息
                e.printStackTrace();
            }
        }
        // 如果所有字段值都相等,则返回true
        return true;
    }

使用示例

使用示例
main 方法中,我们演示了如何使用该工具类进行集合比较,并输出差异信息。运行程序后,将会输出如下结果:

新增的元素:
Person{name='张三4', age=10}
不变的元素:
Person{name='张三', age=10}
Person{name='张三2', age=10}
删除的元素:
Person{name='张三3', age=10}

总结

本文介绍了如何使用Java编写一个工具类来对比两个集合并找出它们之间的差异。通过编写这样一个工具类,我们可以更轻松地处理集合比较的需求,并更好地理解集合之间的关系。希望本文对您有所帮助,欢迎提出建议和意见。

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值