【问题标题】:ignore fields while comparing two lists比较两个列表时忽略字段
【发布时间】:2018-03-29 13:52:31
【问题描述】:

我有两个 Person 对象列表。

Person class has the below attributes
String Name, 
Integer Age, 
String Department, 
Date CreatedTime,
String CreatedBy

当我比较我的列表是否相等时,我不想比较 CreatedTime 和 CreatedBy 字段。

如何使用 Java 8 比较两个列表是否相等,同时忽略 CreatedTime、CreatedBy 字段进行比较?

【问题讨论】:

    标签: collections java-8


    【解决方案1】:

    您甚至不需要 Java-8 的功能来执行此操作,只需像这样覆盖 equals 和 hashCode:

    class Person {
        String name;
        Integer age;
        String department;
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            Person person = (Person) o;
    
            if (name != null ? !name.equals(person.name) : person.name != null) return false;
            if (age != null ? !age.equals(person.age) : person.age != null) return false;
            return department != null ? department.equals(person.department) : person.department == null;
        }
    
        @Override
        public int hashCode() {
            int result = name != null ? name.hashCode() : 0;
            result = 31 * result + (age != null ? age.hashCode() : 0);
            result = 31 * result + (department != null ? department.hashCode() : 0);
            return result;
        }
    }
    

    然后你可以像这样比较两个给定的列表:

     boolean result = firstList.equals(secondList);
    

    编辑:

    根据您的评论:

    我需要这种形式的比较仅用于测试目的。在我的 生产代码我想保留equals和hashcode来比较 所有字段

    你可以像这样定义一个自定义的 equal 方法:

    public static boolean areEqual(List<Person> first, List<Person> second) {
            Objects.requireNonNull(first, "first list must not be null");
            Objects.requireNonNull(second, "second list must not be null");
            return first.size() == second.size() && 
                    IntStream.range(0, first.size()).allMatch(index -> 
                            customCompare(first.get(index), second.get(index)));
    }
    

    或者如果您想允许将 null 传递给 areEqual 方法,那么稍作改动就足够了:

    public static boolean areEqual(List<Person> first, List<Person> second){
            if (first == null && second == null)
                return true;
            if(first == null || second == null ||
                    first.size() != second.size()) return false;
    
            return IntStream.range(0, first.size())
                            .allMatch(index -> 
           customCompare(first.get(index), second.get(index)));
    }
    

    然后是确定两个给定人员对象是否相等的方法:

    static boolean customCompare(Person firstPerson, Person secondPerson){
    
            if (firstPerson == secondPerson) return true;
    
            if (firstPerson.getName() != null
                    ? !firstPerson.getName().equals(secondPerson.getName()) : secondPerson.getName() != null)
                return false;
    
            return (firstPerson.getAge() != null ? firstPerson.getAge().equals(secondPerson.getAge()) : secondPerson.getAge() == null)
                    && (firstPerson.getDepartment() != null
                    ? firstPerson.getDepartment().equals(secondPerson.getDepartment())
                    : secondPerson.getDepartment() == null);
    }
    

    然后这样称呼它:

    boolean result = areEqual(firstList, secondList);
    

    【讨论】:

    • 我需要这种形式的比较仅用于测试目的。在我的生产代码中,我想保留 equals 和 hashcode 来比较所有字段
    • @megan 提供的方法名称可能不是最好的,但我会留给您随意修改。 :)
    • @megan 为测试目的做这种事情是非常非常普遍的!一个好的测试框架会给你一个简单的方法来实现这些东西——我可能会推荐 AssertJ。上面的代码当然是正确的;但是每次你需要比较事物时都做这样的事情会给你的测试增加很多噪音。
    【解决方案2】:

    您可以使用 Guava 的 Streams.zip() 来获得更实用的解决方案。忽略null 检查是否简洁:

    public static boolean comparePersonLists(List<Person> list1, List<Person> list2) {
        if (list1.size() != list2.size()) {
            return false;
        }
    
        return Streams.zip(list1.stream(), list2.stream(), (a, b) ->
            a == b || (a.name.equals(b.name) && a.age.equals(b.age) && a.department.equals(b.department))
        ).allMatch(t -> t);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-23
      • 2011-10-25
      • 1970-01-01
      • 1970-01-01
      • 2012-05-29
      相关资源
      最近更新 更多