Java hashCode()和equals()
方法hashCode()和equals()在插入Java集合的对象中起着不同的作用。最好在JavaDoc中描述这两种方法的特定合同规则。在这里,我只告诉我们他们扮演的角色。它们的用途是什么,所以我们知道为什么它们的实现很重要。
equals()
" equals()"在大多数集合中用于确定集合是否包含给定元素。例如:
List list = new ArrayList(); list.add("123"); boolean contains123 = list.contains("123");
ArrayList迭代所有元素并执行" 123" .equals(element)以确定元素是否等于参数对象" 123"。是String.equals()的实现,它确定两个字符串是否相等。
删除元素时也使用了equals()方法。例如:
List list = new ArrayList(); list.add("123"); boolean removed = list.remove("123");
ArrayList再次迭代其所有元素并执行" 123" .equals(element)以确定元素是否等于参数对象" 123"。它发现等于给定参数" 123"的第一个元素被删除。
如我们所见,.equals()的正确实现对于我们自己的类与Java Collection类一起正常工作至关重要。那么,如何"适当"地实现equals()
呢?
那么,两个对象什么时候相等?这取决于应用程序,类以及我们要尝试执行的操作。例如,假设我们正在加载和处理存储在数据库中的"雇员"对象。这是一个这样的Employee
类的简单示例:
public class Employee { protected long employeeId; protected String firstName; protected String lastName; }
我们可以决定两个" Employee"对象是否相等,只要它们的" employeeId"相等。或者,我们可以决定所有字段必须都等于" employeeId"," firstName"和" lastName"。这是匹配这些条件的equals()
的两个示例实现:
public class Employee { ... public boolean equals(Object o){ if(o == null) return false; if(!(o instanceof) Employee) return false; Employee other = (Employee) o; return this.employeeId == other.employeeId; } }
public class Employee { ... public boolean equals(Object o){ if(o == null) return false; if(!(o instanceof) Employee) return false; Employee other = (Employee) o; if(this.employeeId != other.employeeId) return false; if(! this.firstName.equals(other.firstName)) return false; if(! this.lastName.equals(other.lastName)) return false; return true; } }
这两个实现中的哪一个"合适"取决于我们需要执行的操作。有时我们需要从缓存中查找" Employee"对象。在这种情况下,我们可能需要的是使employeeId
相等。在其他情况下,我们可能需要的还不止此,例如,确定" Employee"对象的副本是否已从原始对象更改。
hashCode()
当将对象插入到HashTable,HashMap或者HashSet中时,将使用对象的hashCode()方法。如果我们不了解哈希表在内部如何工作的理论,则可以在Wikipedia.org上阅读有关hastables的信息。
将对象插入hastable中时,可以使用键。计算该密钥的哈希码,并将其用于确定内部存储对象的位置。当我们需要在哈希表中查找对象时,我们还可以使用键。计算该密钥的哈希码,并将其用于确定在何处搜索对象。
哈希码仅在内部指向某个"区域"(或者列表,存储桶等)。由于不同的密钥对象可能具有相同的哈希码,因此哈希码本身不能保证找到正确的密钥。然后,哈希表会对该区域(所有具有相同哈希码的键)进行迭代,并使用键的" equals()"方法来找到正确的键。找到正确的键后,将返回为该键存储的对象。
因此,如我们所见,在存储和查找哈希表中的对象时,会使用hashCode()
和equals()
方法的组合。
如果Java Collections API中的哈希表能够正常工作,那么以下两个关于在我们自己的类中实现hashCode()
方法的知识非常有用:
- 如果object1和object2根据其equals()方法相等,则它们还必须具有相同的哈希码。
- 如果object1和object2具有相同的哈希码,则它们也不必相等。
简而言之:
- 如果相等,则也使用相同的哈希码。
- 相同的哈希码不能保证相等。
这是与前面显示的equals()方法匹配的hashCode()方法的两个示例实现:
public class Employee { protected long employeeId; protected String firstName; protected String lastName; public int hashCode(){ return (int) employeeId; } }
public class Employee { protected long employeeId; protected String firstName; protected String lastName; public int hashCode(){ return (int) employeeId * firstName.hashCode() * lastName.hashCode(); } }
注意,如果两个" Employee"对象相等,则它们也将具有相同的哈希码。但是,正如在第一个示例中特别容易看到的那样,两个" Employee"对象可以不相等,并且仍具有相同的哈希码。
在两个示例中,哈希码都是将" employeeId"四舍五入为" int"。这意味着许多雇员ID可能导致相同的哈希码,但是这些"雇员"对象仍然不相等,因为它们没有相同的雇员ID。