详解Java的equals(Object obj)方法:指示其他某个对象是否与此对象“相等”

  • Post category:Java

Java的equals(Object obj)方法

在Java中,equals是一个非常重要的方法,用来比较两个对象是否相等。默认情况下,equals方法比较两个对象的地址是否相等,而不是比较对象的属性是否相等。因此,当我们自定义的类需要比较两个对象是否相等时,我们需要重写equals方法。

equals方法的常规写法

一个常规的equals方法的写法如下所示:

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    MyClass other = (MyClass) obj;
    if (this.field1 != other.field1) {
        return false;
    }
    if (!Objects.equals(this.field2, other.field2)) {
        return false;
    }
    return true;
}

上面代码中,equals方法接收一个参数obj,返回一个boolean类型的值。首先判断两个对象的地址是否相等,如果是则直接返回true。然后判断obj是否为null,如果是则直接返回false。接着判断两个对象的类型是否相同,如果不同则直接返回false。然后将obj转换为自定义对象类型,并逐个比较对象的属性是否相等。最后如果所有属性都相等,则返回true,否则返回false

示例1: 自定义类的equals方法

下面是一个自定义的类Person,它有两个属性 name 和 age,重写了equals方法用于比较两个对象是否相等。

class Person {
    private String name;
    private int age;

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Person person = (Person) obj;
        return age == person.age && Objects.equals(name, person.name);
    }
}

我们可以使用下面的代码来测试equals方法的正确性:

        Person p1 = new Person("Tom", 20);
        Person p2 = new Person("Tom", 20);
        Person p3 = new Person("Jerry", 30);
        System.out.println(p1.equals(p2)); // true
        System.out.println(p1.equals(p3)); // false

在上面的代码中,我们可以看到,两个Person对象如果它们的姓名和年龄相等,则我们认为它们是相等的。

示例2: 使用equals方法的List集合删除元素

有时候我们需要从一个List集合中删除一个元素,我们可以使用remove方法,但是这个方法有一个不好的地方,就是当我们需要删除的元素在集合中出现多次时,它只会删除第一个出现的元素。为了解决这个问题,我们可以使用equals方法来自定义两个元素是否相等。

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

class TreeNode {
    private String id;
    private String parentId;
    private List<TreeNode> children;

    public TreeNode(String id, String parentId) {
        this.id = id;
        this.parentId = parentId;
        this.children = new ArrayList<>();
    }

    public void addChild(TreeNode child) {
        children.add(child);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        TreeNode node = (TreeNode) obj;
        return Objects.equals(id, node.id) && Objects.equals(parentId, node.parentId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, parentId);
    }

    public String getId() {
        return id;
    }

    public String getParentId() {
        return parentId;
    }

    public List<TreeNode> getChildren() {
        return children;
    }
}

public class Main {
    public static void main(String[] args) {
        TreeNode root = new TreeNode("1", null);
        TreeNode node2 = new TreeNode("2", "1");
        TreeNode node3 = new TreeNode("3", "1");
        TreeNode node4 = new TreeNode("4", "2");
        root.addChild(node2);
        root.addChild(node3);
        node2.addChild(node4);
        node2.addChild(new TreeNode("5", "2"));
        node2.addChild(new TreeNode("6", "2"));

        System.out.println(root.getChildren().size()); // 2
        TreeNode nodeToRemove = new TreeNode("2", "1");
        root.getChildren().remove(nodeToRemove);
        System.out.println(root.getChildren().size()); // 1
    }
}

上面代码中,我们定义了一个TreeNode类,它有三个属性,分别是节点的idparentId和子节点的列表children。我们在TreeNode类中重写了equals方法和hashCode方法,使得两个节点在idparentId相等时认为它们是相等的。

接下来,在main方法中,我们创建了一个树状结构,并根据某些条件选择某个节点,然后使用remove方法从树结构中删除该节点。由于重写了equals方法,remove方法现在可以正确地删除集合中的所有相等元素。

结论

在Java中,equals方法是用来比较两个对象是否相等的一种方法。默认情况下,equals方法比较的是对象的地址,而不是比较属性。我们需要重写equals方法,以便我们自定义的对象可以正确地使用equals方法进行比较。