我们可以对收集算法使用自定义的equals方法吗?

时间:2018-07-09 19:07:42

标签: java

我有一个自定义类作为Student,它具有两个不同的equals方法(equals,equals1),并且具有两个Student对象集合,分别为list1和list2。当我确实使用list1.retainAll(list2)时,需要使用equals1机制而不是eqauls方法。

这是可能的吗?或者,如果我们的客户类中有多个equals机制,我们是否有任何API提及equals方法名称。

示例:

class Student {

    public String name;

    public Student(String name) {
        this.name = name;
    }

    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    public boolean equals1(Object obj) {
        if(obj == null) return false;
        if(!(obj instanceof Student)) return false;
        Student student = (Student) obj;
        if(this.name.equals(student.name)) {
            return true;
        } else {
            return false;
        }
    }
}

public class Demo {

    public static void main(String[] args) {

        List<Student> list1 = new ArrayList<Student>();
        list1.add(new Student("AAA"));
        list1.add(new Student("BCD"));

        List<Student> list2 = new ArrayList<Student>();
        list2.add(new Student("AAA"));
        list2.add(new Student("CDE"));

        // Intersection of list1 and list2
        list1.retainAll(list2);

        for (Student student : list1) {
            System.out.println(student.name);
        }
    }
}

如果使用equals1方法,则预期结果为[AAA],但在这种情况下,将执行默认的equals方法,因此结果为空。

我们如何使用自定义equals方法进行收集算法。

2 个答案:

答案 0 :(得分:1)

equals()很特别

请记住equals()是特殊的,因为整个 collections API都依赖于它。

此外, collections API(至少具有名称为“ HashSetHashTable的“哈希”的API)依赖于equals()之间的关系和hashcode() :交易是equals()返回true时,两个对象都从hashcode()返回相同的值。最重要的是,hashcode()重调的值在对象生存期内一定不能更改。

由于您的equals1()方法使用了 mutable 字段name,因此您的实现有可能违反此规则,导致 collections API失败。

答案 1 :(得分:0)

您可以创建用于包装实体和等价物的等价物包装器 它会像:

public class EqulasWrapper<T extends CustomHashCode> {

    T entity;
    BiFunction<T, T, Boolean> customEquals;


    public EqulasWrapper(T entityClass, BiFunction<T, T, Boolean> func){
        this.entity = entityClass;
        this.customEquals = func;
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        EqulasWrapper<T> that = (EqulasWrapper<T>) o;
        return this.customEquals.apply(this.entity, that.entity);
    }

    @Override
    public int hashCode() {
        return entity.getCustomHashCode();
    }


    public static class Person implements CustomHashCode {
        private int age;
        private String name;

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

        @Override
        public int getCustomHashCode() {
            return age;
        }
    }

    public T getEntity() {
        return entity;
    }

    public BiFunction<T, T, Boolean> getCustomEquals() {
        return customEquals;
    }

    public static void main(String[] args) {
        Person person = new Person(10, "Dan");
        BiFunction<Person, Person, Boolean> myCustomEqualsFunc =
                (p1, p2) -> p1.age == p2.age;

        EqulasWrapper<Person> personEqulasWrapper = new EqulasWrapper<>(person, myCustomEqualsFunc);

        Set<EqulasWrapper> mySet = new HashSet<>();

        mySet.add(personEqulasWrapper);

    }

CustomHashCode界面如下:


public interface CustomHashCode {

    int getCustomHashCode();

}

简短说明

您的集合将使用您的实体实现的自定义哈希代码,而该自定义等于您给他的代码。

因此您可以使用EqulasWrapper类型创建其他集合 并设计您的哈希码和equals函数,集合将使用包装器而不是原始哈希码和equals

希望我有所帮助 如果您有任何疑问,我想听听。