美文网首页
使用equals和hashcode 比较java对象

使用equals和hashcode 比较java对象

作者: AD刘涛 | 来源:发表于2020-03-05 21:49 被阅读0次

使用equalshashcode 比较java对象

equalshashcode之间的关系是什么?当比较java对象时,如何使用这两个方法?

在这篇文章中,您将了解如何将equals()hashcode()结合起来,使Java程序中的对象比较变得高效和简单。简单地说,将使用这些方法来验证两个对象是否具有相同的值。

如果没有equals()hashcode(),我们将不得不使用非常多的if进行比较,分别比较对象中的每个字段。这将使代码非常混乱和难以阅读。然而使用这两种方法将帮助我们创建更加灵活和良好的代码结构。

在java中重写 equals() and hashcode()方法

重载是为了使用多态而出现的一种技术:父类或接口的行为在子类中被重写(覆盖)。Java中的每个object都包含一个equals()和一个hashcode()方法,但是必须重写它们才能正常使用。

为了理解如何使用equals()hashcode()方法进行重载,我们可以在核心Java类中研究它们的实现。下面是object类中的equals()方法。该方法正在检查当前实例是否与先前传递的对象相同。

public boolean equals(Object obj) {
        return (this == obj);
}

hashcode()方法未被重写时,将调用对象类中的默认方法。这是一个native方法,这意味着它将以另一种语言(如C)执行,并将返回一些有关对象的内存地址。

@HotSpotIntrinsicCandidate
public native int hashCode();

equals()hashcode()方法没有被重写时,您将看到上面的方法被调用。在本例中,这些方法并没有实现equals()hashcode()的真正目的,即检查两个或多个对象是否具有相同的值。

通常,当您重写equals()时,还必须重写hashcode()

使用equals()比较对象

我们使用equals()方法来比较Java中的对象。为了确定两个对象是否相同,我们使用equals()比较对象属性值。

public class EqualsAndHashCodeExample {

    public static void main(String... equalsExplanation) {
        System.out.println(new Simpson("Homer", 35, 120)
                 .equals(new Simpson("Homer",35,120)));
        
        System.out.println(new Simpson("Bart", 10, 120)
                 .equals(new Simpson("El Barto", 10, 45)));
        
        System.out.println(new Simpson("Lisa", 54, 60)
                 .equals(new Object()));
    }
    
    static class Simpson {

        private String name;
        private int age;
        private int weight;

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

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Simpson simpson = (Simpson) o;
            return age == simpson.age &&
                    weight == simpson.weight &&
                    name.equals(simpson.name);
        }
    }

}

在第一个比较中,equals()将当前对象实例与已传递的对象进行比较。如果两个对象具有相同的值,则equals()将返回true

在第二个比较中,equals()检查传递的对象是否为null,或者判断其类型是否相同。如果对象类型不同,那么对象则不相等。

最后,equals()比较对象字段。如果两个对象具有相同的字段值,那么它们就是相同的。

代码分析

现在,让我们在main()方法中查看这些对象的比较结果。首先,我们比较两个Simpson对象:

System.out.println(new Simpson("Homer", 35, 120).equals(new Simpson("Homer", 35, 120)));

这里的对象是相同的,所以结果将为真。

接下来,我们再次比较两个Simpson对象:

System.out.println(new Simpson("Bart", 10, 45).equals(new Simpson("El Barto", 10, 45))); 

这两个object几乎一模一样,但它们的name字段的值却不一样:BartElBarto。因此,结果将是false

最后,让我们比较一个Simpson 对象和一个类对象实例:

System.out.println(new Simpson("Lisa", 54, 60).equals(new Object())); 

在这个案例中,由于对象类型不同,结果将为false

equals()== 区别

乍一看,==操作符和equals()方法似乎做了相同的事情,但实际上它们是两种不同的操作。操作符==比较两个对象引用是否指向同一地址,即判断两个对象是不是同一个对象。例如

System.out.println(homer == homer2);

该代码中,我们使用new操作符实例化了两个不同的Simpson实例。因此,变量homerhomer2将指向内存堆中的不同对象引用。结果是false

System.out.println(homer.equals(homer2));

而这段代码中,我们重写了equals()方法。在这种情况下,只比较names。因为两个Simpson对象的names都是Homer,所以结果将为true

使用 hashcode() 来辨别对象

在比较对象时,我们使用hashcode()方法来优化性能。执行hashcode()将为程序中的每个对象返回一个唯一ID,这使得比较对象的整个状态变得更加容易。

如果一个对象的hashcode与另一个对象的hashcode不同,那么就没必要执行equals()方法:因为你可以通过hashcode得知这两个对象并不相同。另一方面,如果hashcode相同,那么就有必要执行equals()方法来确定这两个对象的所有字段值是否相同。

这里有一个hashcode()的实际例子:

public class HashcodeConcept {

    public static void main(String... hashcodeExample) {
        Simpson homer = new Simpson(1, "Homer");
        Simpson bart = new Simpson(2, "Homer");

        boolean isHashcodeEquals = homer.hashCode() == bart.hashCode();

        if (isHashcodeEquals) {
            System.out.println("Should compare with equals method too.");
        } else {
            System.out.println("Should not compare with equals method because " +
                    "the id is different, that means the objects are not equals for sure.");
        }
    }

     static class Simpson {
        int id;
        String name;

        public Simpson(int id, String name) {
            this.id = id;
            this.name = name;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Simpson simpson = (Simpson) o;
            return id == simpson.id &&
                    name.equals(simpson.name);
        }

        @Override
        public int hashCode() {
            return id;
        }
    }
}

hashcode()总是返回相同值是有效的,但不是那么高效。在这个案例中,这段代码将返回true,所以equals()方法总是会被执行。在这种情况下,没有性能上的改进。

参考文档

相关文章

网友评论

      本文标题:使用equals和hashcode 比较java对象

      本文链接:https://www.haomeiwen.com/subject/udwkrhtx.html