简体   繁体   English

Equals() 方法和 hashcode() 理解问题

[英]Equals() method and hashcode() understanding issue

This is a practice exercise from a book by Koffman.这是 Koffman 一本书中的练习。 Data Structures: Abstraction and Design Using Java, 3rd Edition.数据结构:抽象和设计使用 Java,第 3 版。

I have a series of questions.我有一系列的问题。 I have had 2 attempts at the equals method.我对 equals 方法进行了 2 次尝试。 Lines 21-29 are what made sense to me logically without checking references, and 32-41 are adapted from the book.第 21-29 行是我在没有检查参考资料的情况下在逻辑上有意义的内容,而第 32-41 行是从书中改编的。

  1. Are lines 20-30 a correct implementation of an equals() override method?第 20-30 行是 equals() 覆盖方法的正确实现吗? Can I have 2 String parameters and check if these parameters match with the Person Objects 2 String parameters?我可以有 2 个字符串参数并检查这些参数是否与 Person 对象的 2 个字符串参数匹配吗?

  2. Lines 33-41 I have no idea what is occurring or if it's correct.第 33-41 行我不知道发生了什么或者它是否正确。 I stole the code from the book but changed implementation here for 2 String parameters?我从书中窃取了代码,但在这里更改了 2 个字符串参数的实现?

    2 a) Are these lines correct to start with? 2 a) 这些行一开始是正确的吗?

    2 b) What does instanceof on line 34 check for exactly here? 2 b) 第 34 行的 instanceof 在这里检查什么? Just that Person is an Object too?只是那个人也是 Object 吗? Or more?或者更多?

    2 b 1) If there's more to 2a, what else is being checked? 2 b 1) 如果 2a 还有更多内容,还要检查什么?

3 ) Line 45 and 46, What is this method actually doing? 3 ) 第 45 和 46 行,这个方法实际上在做什么?

1 public class Person {
2   
3   String lastName;
4   String firstName;
5   
6   
7   public Person(String lastName, String firstName) {
8       this.lastName = lastName;
9       this.firstName = firstName;
10  }
11  
12  public String toString() {
13      
14      String result = ("First name: " + firstName +
15              "\nLast name: " + lastName);
16              
17      return result;
18  }
19  
20  public boolean equals(String lastName, String firstName) {
21
22      if (this.lastName == lastName && this.firstName == firstName) {
23  
24          
25          return true;    
26      }
27      
28      return false;
29      
30  }
31  
32  
33  public boolean equals(Object obj) {
34      if (obj instanceof Person) {
35              return firstName.equals(((Person) obj).firstName)
36                      && lastName.equals(((Person) obj).lastName);
37              
38      }
39          
40      return false;
41  }
42  
43  
44  
45   public int hashcode() {
46       return lastName.hashCode() + firstName.hashCode();
47   }
48  
49  
50
51
52 }

Are lines 20-30 a correct implementation of an equals() override method?第 20-30 行是 equals() 覆盖方法的正确实现吗?

No.不。

this.lastName == lastName

This compares the reference identity of this.lastName with the reference identity of parameter lastName .这会将this.lastName引用标识与参数lastName的引用标识进行比较。 You don't want that - you can have 2 identical strings that aren't the same actual object. What you want is this.lastName.equals(lastName) , though it needs null-guarding.你不想要那个 - 你可以有 2 个相同的字符串,但实际 object 不同。你想要的是this.lastName.equals(lastName) ,尽管它需要 null-guarding。 (So, really, if (this.lastName == null) return lastName == null; return this.lastName.equals(lastName); ). (所以,真的, if (this.lastName == null) return lastName == null; return this.lastName.equals(lastName); )。

public boolean equals(String lastName, String firstName) {

This isn't an equals method.这不是一个 equals 方法。 The equals method has signature boolean equals(Object other) {} . equals 方法的签名boolean equals(Object other) {} Line 33's is the right signature.第 33 行是正确的签名。

return firstName.equals(((Person) obj).firstName)

Isn't nullsafe.不是空安全的。 equals methods are not supposed to throw anything. equals 方法不应该抛出任何东西。 See above on how to fix that.请参阅上文了解如何解决该问题。

return lastName.hashCode() + firstName.hashCode();

Again the null thing is a problem here, otherwise, eh, it's fine. null 又是这里的问题,否则,嗯,没关系。 You could do better, but that'd just be an optimization.你可以做得更好,但这只是一种优化。 The reason this is slightly suboptimal is esoteric.这有点次优的原因是深奥的。 (It gives the same hashcode for eg "Peter Jackson" and "Jackson Peter", which is slightly suboptimal). (它为例如“Peter Jackson”和“Jackson Peter”提供了相同的哈希码,这有点次优)。

Lines 33-41 I have no idea what is occurring or if it's correct.第 33-41 行我不知道发生了什么或者它是否正确。 I stole the code from the book but changed implementation here for 2 String parameters instead of the 1 Int parameter they had (IDNumber) on page 355 in the textbook.我从书中窃取了代码,但在此处更改了 2 个 String 参数的实现,而不是教科书第 355 页上的 1 个 Int 参数 (IDNumber)。

I don't have your textbook, you didn't mention it.我没有你的教科书,你没有提到它。 Nobody on Stack Overflow can answer this question as a consequence.因此,Stack Overflow 上没有人可以回答这个问题。 An equals method must look like public boolean equals(Object other) . equals 方法必须类似于public boolean equals(Object other) Period.时期。

What does instanceof on line 34 check for exactly here?第 34 行的 instanceof 在这里检查什么? Just that Person is an Object too?只是那个人也是 Object 吗? Or more?或者更多?

I can ask you if this book is equal to that dog.我可以问你这本书是否等于那只狗。 The answer is a rather obvious: Uh, no.答案很明显:呃,不。

The same thing is happening here.同样的事情也发生在这里。 Object is the supertype of many things. Object是许多事物的超类型。 I might be doing this:我可能会这样做:

Person joe = new Person("joe");
Person jane = new Person("jane");
joe.equals(jane);

In which case we'd have to look at names to figure it out.在这种情况下,我们必须查看名称才能弄清楚。 (the other instanceof Person check would succeed). other instanceof Person检查会成功)。

But I could also do:但我也可以这样做:

Person joe = new Person("joe");
Dog rover = new Dog("rover");
joe.equals(rover);

In which case the instanceof check will fail, and we want it to, because if you try to cast the parameter to Person , it would fail - it isn't (it's a dog).在这种情况下,instanceof 检查将失败,而我们希望它失败,因为如果您尝试将参数转换为Person ,它将失败——它不是(它是一只狗)。 The equals method should return false , it should not throw an exception. equals 方法应该返回false ,它不应该抛出异常。

Line 45 and 46, I've read that this checks the memory address of the object.第 45 和 46 行,我读到这会检查 object 的 memory 地址。

You've read a lie then.那你读了一个谎言。 That's.. just incorrect and makes no sense at all.那是.. 只是不正确,根本没有意义。 This invokes the hashCode() method on whatever object the lastName field is pointing at.这会在lastName字段指向的任何 object 上调用hashCode()方法。 There's no need to know how it works.没有必要知道它是如何工作的。 It does not return memory addresses.它不返回 memory 地址。 If it did, this would be broken (as the hashCode of 2 objects whose value are identical, but which do not live at the same memory address, must return the same hashcode, that's the point of hashcode: Equal objects must have equal hashcode (but equal hashcode does not neccessarily mean equal objects).如果是这样,这将被破坏(因为 2 个对象的哈希码,其值相同,但不在同一个 memory 地址,必须返回相同的哈希码,这就是哈希码的要点:相等的对象必须具有相等的哈希码(但相等的哈希码并不一定意味着相等的对象)。

In general you should not be writing your own equals and hashCode implementations.一般来说,您不应该编写自己的 equals 和 hashCode 实现。 Let java do it (records), your IDE do it (the source menu has a 'generate' optino), or let tools like Project Lombok or AutoValue do it.让 java 来做(记录),你的 IDE 来做(源菜单有一个“生成”optino),或者让像 Project Lombok 或 AutoValue 这样的工具来做。

Think of a Java object as a person and its hashcode() as the address of the house he/she lives in. Multiple persons can live in the same house (sharing the same hashcode ) so once you arrive at the correct house, you will need an additional mechanism to find the actual person you are looking for.把 Java object 想象成一个人,把它的hashcode()想象成他/她住的房子的地址。多个人可以住在同一所房子里(共享相同的hashcode ),所以一旦你到达正确的房子,你就会需要一个额外的机制来找到你要找的人。 That's where equal() comes into play.这就是equal()发挥作用的地方。 Two people in that house are seen as "different" if and only if equal() tells you so.当且仅当equal()告诉您时,那所房子里的两个人才被视为“不同”。

By default, Java's equal() compares the references of the two objects.默认情况下,Java 的equal()比较两个对象的引用。 However, you can override equal() to implement your own criteria of when two people should be treated as the same person.但是,您可以覆盖equal()以实施您自己的标准,即何时应将两个人视为同一个人。 Two people can have completely different identities, but as long as your criteria say that they're equal() , then they are treated as one and the same person.两个人可以有完全不同的身份,但只要你的标准说他们是equal() ,那么他们就会被视为一个人和同一个人。

So, with that in mind所以,考虑到这一点

Are lines 20-30 a correct implementation of an equals() override method?第 20-30 行是 equals() 覆盖方法的正确实现吗?

No, since you are comparing two persons, not two string不,因为你是在比较两个人,而不是两个字符串

Lines 33-41 I have no idea what is occurring or if it's correct第 33-41 行我不知道发生了什么或者它是否正确

33  public boolean equals(Object obj) {
34      if (obj instanceof Person) {
35              return firstName.equals(((Person) obj).firstName)
36                      && lastName.equals(((Person) obj).lastName);
37              
38      }
39          
40          return false;
41  }

Says, you choose a random person in the house and want to check if this person is the same person as another object, but the other object can literally be anything (TV, fridge, trashbin, etc.).说,你在房子里随机选择一个人,想检查这个人是否与另一个 object 是同一个人,但另一个 object 可以是任何东西(电视、冰箱、垃圾桶等)。 As the first step you want to verify that the other object is indeed a person (line 34).作为第一步,您要验证另一个 object 确实是一个人(第 34 行)。 If that is the case, then invoke your equal criteria to judge if the two should be treated as the same person (line 35 and 36).如果是这样,那么调用你的equal标准来判断两人是否应该被视为同一个人(第 35 和 36 行)。

Line 45 and 46, I've read that this checks the memory address of the object. But given that we only return lastName.hashCode() and firstName.hashCode(), where abouts is it checking for comparison of memory addresses?第 45 和 46 行,我读到这会检查 object 的 memory 地址。但是鉴于我们只返回 lastName.hashCode() 和 firstName.hashCode(),它在哪里检查 memory 地址的比较? What is this method actually doing?这个方法实际上在做什么?

It returns the address of the "bucket" of memory that the object and possibly other objects also live in. That is, it returns the address of the share house.它返回 memory 的“桶”的地址,object 和可能的其他对象也居住在该桶中。也就是说,它返回共享房屋的地址。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM