//es pseudocódigo, no es código Java
//se utiliza una matriz para guardar los elementos
Object[][] conjunto = ...
metodo agregar (elemento)
int hash = nuevo.hashCode();
si (hash < conjunto.length)
//pueden haber varios elementos con el mismo hash
//por ello se utiliza una matriz
//el hash ayuda a
Object[] elementosConMismoHash = arreglo[hash];
var encontrado = falso;
para cada Object actual en elementosConMismoHash
si actual.equals(nuevo) entonces
encontrado = verdadero;
romper para;
fin si
fin para
si no fue encontrado entonces
agregar nuevo en elementosConMismoHash
fin si
fin si
fin metodo
Java 中的每个类总是继承自 class
Object
,这是继承层次结构中的第一个类。正是在这个类中定义了两个方法,通过继承,每个对象都Java
可以调用:关于第一种方法,目标
hashCode
是返回一个整数,当对象保存在称为HashMap(或其他类似Hashtable、HashSet的其他数据结构)中时,该整数“标识”对象,其目标是存储一组值(形式类似于 aArrayList
或数组)。这些结构,除了一些区别外,以下列方式持久化数据:当想要在这个结构中保存一个对象时,调用该方法
hashCode()
,正如我提到的,它返回一个整数,该结构将使用它来决定将这些数据保存在哪个“桶”中。现在,如果我想检索我保存的对象,我hashCode
再次调用该方法,从而确定从哪个抽屉中检索对象(就像我保存键/值数据时,它调用hashCode
键的方法来获取相应的值) . 以这种方式保存数据并调用该方法的目的是实现恒定时间的存储和检索(并非总是如此,但也很接近)。这是否不会发生几乎总是取决于每个对象的 hashCode() 方法返回的值。假设我们在这个结构中保存了 3 个对象,并且
hashCode
3 的方法返回 0,这意味着这 3 个对象将存储在抽屉 0 中。如果我想恢复它们,就会发生我现在必须遍历我的对象已保存在此抽屉中以确定我想要哪一个?因此,这些对象的 hashCode() 方法是没有用的,因为这样做的结果是,当保存元素时,它们会均匀地分散在整个结构中(剩下的空抽屉数量最少,并且没有抽屉可以存放更多项目比其他人存储)。关于
hashCode
类方法的实现Object
,标识符native
表示编译器有责任确定它将如何执行此任务。在我审查过的所有实现中,它本机返回对象所在的“内存地址”的数字表示。这似乎是一个很好的默认策略,但它有一个大问题:内存地址比“桶数”多得多,因此该结构通过为其分配hashcode()%MAX_LENGTH
MAX_LENGTH 的桶号来解决问题(同样,这也取决于实现)数组的最大大小。因此,要存储的元素数量越多,结构中存在多余元素的抽屉的可能性就越大。因此,如果您需要在这种类型的结构中存储元素,
Java
建议重写此方法。Eclipse 或 Netbeans 等一些 IDE 允许您从类属性生成方法hashCode
,这足以解决这个问题。关于第二种方法,
equals()
类的默认实现Object
很明确:它比较对象之间的引用。equals()
因此,在定义类时不覆盖它是一个非常糟糕的主意,因为调用和使用 operator之间没有区别==
。文档清楚地指出了此方法在比较时应具有的功能:true
.true
,那么对象 B 与对象 A 的比较也必须返回true
。true
,并且将对象 B 与另一个对象 C 进行比较并返回true
,则在将对象 A 与对象 C 进行比较时,它应该返回true
。现在,您会注意到, method
equals()
不会调用 methodhashCode()
,那么为什么要hashCode()
在 method 被覆盖时覆盖 methodequals()
呢?最简单的答案是因为文档建议如此:如果两个对象相等,则它们必须具有相同的返回值hashCode()
。尽管是一个建议,但对这些结构的操作再次说明了为什么有必要:如果两个对象具有相同的 hashCode,则两个对象将存储在同一个桶中,该结构现在使用该equals()
桶内的方法来确定哪个对应到请求的那个,为此它取决于您是否覆盖了该方法,否则它不能保证正确的结果。总之:
equals()
建议也重写该方法hashCode()
以保留两个方法之间的约定:两个相同的对象必须返回相同的哈希值。该方法equals()
不调用该方法hashCode()
来确定两个对象的相等性。equals()
,因为默认实现不是很有帮助。hashCode()
,即使两个不同的对象也可以返回相等的哈希值。HashMap
等等),那么重写该方法是绝对必要的hashCode()
,否则在对数据执行保存、查询或删除操作时会得到意外或不希望的结果。不,该方法的作用
equals
是评估一个对象是否等于另一个对象。如果一个类没有重写方法equals
,那么使用的结果将与在对象之间equals
使用运算符相同。==
该方法hashCode
不与使用方法评估相关联equals
。该方法
hashCode
用于获取类似于对象标识符的哈希码。此哈希用于某些集合,例如HashSet
,HashMap
,LinkedHashSet
,LinkedHashMap
,ConcurrentHashMap
等。散列的作用是帮助容器定位集合结构中的元素,并帮助搜索具有所述散列的对象是否已经存在,这样可以确保 O(1) 的搜索时间(假设冲突的数量很低) .一个算法如何工作的例子,在哪里使用和
HashSet#add
方法。(是个想法,实际实现更复杂,使用更多的机制来保证内部结构的大小是增加还是减少,不过那是题外话)hashCode
equals
如您所见,
hashCode
用作标识符,但可以有多个元素具有相同的结果hashCode
。这并不能保证使用equals
.由于该方法的效率,
equals()
通常在开始时比较两个对象的hashcode,这样如果不相等,则立即返回false
,避免了其余的比较。