Object.hashCode() 详解

简介: 在Java编程中,hashCode方法是一个常见而重要的概念。它通常用于哈希表、集合以及一些需要高效检索数据的数据结构中。然而,对于许多开发者来说,hashCode方法可能是一个容易被忽略或者被简单实现的部分。在本文中,我们将深入探讨Java中hashCode的一些思考,以便更好地理解其背后的原理和影响。

在Java编程中,hashCode方法是一个常见而重要的概念。它通常用于哈希表、集合以及一些需要高效检索数据的数据结构中。然而,对于许多开发者来说,hashCode方法可能是一个容易被忽略或者被简单实现的部分。在本文中,我们将深入探讨Java中hashCode的一些思考,以便更好地理解其背后的原理和影响。

hashcode.jpg

hashCode的简介

hashCode 返回的 "散列码" 是指通过哈希算法生成的一个整数,用于标识对象的唯一性。在Java中,hashCode方法被设计用来支持基于哈希的集合类,如HashMap、HashSet等,以及其他需要快速检索数据的数据结构。

hashCode的意义

  • 快速检索

散列码的主要作用是提高数据结构的检索效率。在哈希表中,通过散列码可以迅速定位到存储数据的位置,而不需要遍历整个数据集。这对于大规模数据集的快速检索非常重要,能够使得检索操作的时间复杂度接近常数级别。

  • 哈希集合性能

在使用哈希集合(如HashSet)时,散列码决定了元素在集合中的存储位置。如果不同的对象具有相同的散列码,就会发生哈希冲突,需要通过其他手段解决,如链地址法或开放寻址法。因此,好的散列码设计能够最小化哈希冲突,提高哈希集合的性能。

  • equals方法辅助

hashCode方法与equals方法是相关联的。在Java中,根据对象相等性的定义,如果两个对象相等(equals方法返回true),那么它们的散列码应该相等。这一关系有助于在哈希集合中正确地比较和存储对象。

  • 分布均匀

散列码的设计应尽量使得不同的对象生成不同的散列码,以减少哈希冲突的可能性。这需要考虑到对象的各个属性,确保它们都对最终的散列码有贡献,避免简单地依赖于某一个属性。

重写 hashCode 方法

为什么要重写 hashCode 方法

Object类中提供的默认实现是与当前线程有关的随机数和其他三个固定值进行xorshift运算后的结果数。这种默认实现在实际应用中可能并不总是满足需要,特别是当我们需要基于对象的内容来计算哈希码时。

源码如下:

public native int hashCode();

如何重写hashCode方法

在自定义类中,如果希望基于对象的内容生成哈希码,通常需要重写hashCode()方法。为了简化哈希码的计算,我们可以使用Objects工具类,提供了hash方法,可以接受多个参数,并根据它们生成一个合并后的哈希码。

示例如下:

@Data
public class UrlEntity {
   
   
    private Integer id;
    private String url;

    @Override
    public boolean equals(Object o) {
   
   
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UrlEntity entity = (UrlEntity) o;
        return Objects.equals(id, entity.id) && Objects.equals(url, entity.url);
    }

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

哈希冲突

由于哈希码是一个有限位数的整数,不同的对象可能生成相同的哈希码,这就是哈希冲突。为了最小化哈希冲突的概率,好的哈希码应该能够均匀分布。在实际应用中,可以通过一些技巧和算法来提高哈希码的质量,减少冲突的可能性。

比如如下代码:

public static void main(String[] args) {
   
   
    String str1 = "3C";
    String str2 = "2b";
    System.out.println("字符串"+str1+"的hashCode值为:"+str1.hashCode());
    System.out.println("字符串"+str2+"的hashCode值为:"+str2.hashCode());
}

运行结果为:

字符串3C的hashCode值为:1648
字符串2b的hashCode值为:1648

不同的对象,却拥有了相同的 hashCode值, 这就是哈希冲突。

为什么重写equals方法时一定要重写hashCode方法

在Java中,equals 方法和 hashCode 方法之间存在一种协定,这个协定规定了如果两个对象根据 equals 方法被认为相等,那么它们的 hashCode 值必须相等。反之亦然,如果两个对象的 hashCode 值相等,它们不一定要相等。

这一规定的原因在于,在使用基于散列的集合类(例如 HashMap、HashSet 等)时,对象的 hashCode 值通常用于确定对象在内部存储结构中的位置。当你在集合中使用对象时,集合会首先检查对象的 hashCode 值,然后再使用 equals 方法来确保这个位置上没有相等的对象。

如果你重写了 equals 方法但没有重写 hashCode 方法,那么可能会导致违反这个协定,即相等的对象具有不同的 hashCode 值。这样的情况会导致在使用散列集合时出现问题,因为相等的对象应该被视为相等,它们应该在集合中占据相同的位置。

总结

在Java中,Object.hashCode()方法在处理集合类和对象比较时发挥着关键作用。了解其原理以及如何正确重写这个方法对于编写高效、正确的代码至关重要。通过理解哈希码的生成方式,我们可以更好地利用Java的集合类,并确保我们的自定义类在使用这些类时能够正确地工作。

目录
相关文章
|
1月前
|
存储 Java 对象存储
当hashCode相同时,equals是否也相同?
当hashCode相同时,equals是否也相同?
14 0
|
2月前
|
存储 Java
为什么要重写hashCode()和equals()(深入了解)
为什么要重写hashCode()和equals()(深入了解)
|
存储 NoSQL
简单讲一下 HashCode() 与 equals()方法
简单讲一下 HashCode() 与 equals()方法.
88 0
|
存储 缓存 Java
深入理解= = 、equals()与hashcode()的关系
理解= = 、equals()与hashcode()的关系
深入理解= = 、equals()与hashcode()的关系
hashCode和equals的区别
hashCode和equals的区别
287 0
|
存储 Java 索引
都2022年了,不会还有人hashCode方法都讲解不清楚吧
都2022年了,不会还有人hashCode方法都讲解不清楚吧
|
Java 索引
hashCode和equals的区别(一)
Hello,大家好,我是子悠,作为本周的小编我已经不想跟大家介绍自己了,这篇文章让我们跟随 Jay Pan( 哇,一位新作者哦)的步伐学习知识吧。下面是正文。 有面试官会问:你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?equals和hashCode都是Object对象中的非final方法,它们设计的目的就是被用来覆盖(override)的,所以在程序设计中还是经常需要处理这两个方法。下面我们一起来看一下,它们到底有什么区别,总结一波!
|
测试技术
hashCode和equals的区别(二)
Hello,大家好,我是子悠,作为本周的小编我已经不想跟大家介绍自己了,这篇文章让我们跟随 Jay Pan( 哇,一位新作者哦)的步伐学习知识吧。下面是正文。 有面试官会问:你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?equals和hashCode都是Object对象中的非final方法,它们设计的目的就是被用来覆盖(override)的,所以在程序设计中还是经常需要处理这两个方法。下面我们一起来看一下,它们到底有什么区别,总结一波!
|
存储 缓存 算法
关于 equals 和 hashCode,看这一篇真的够了!
这几天在尝试手撸一个类似Lombok的注解式代码生成工具,用过Lombok的小伙伴知道,Lombok可以通过注解自动帮我们生产equals()和hashCode()方法,因此我也想实现这个功能,但是随着工作的深入,我发现其实自己对于equals()和hashCode()的理解,也处在一个很低级的阶段。
关于 equals 和 hashCode,看这一篇真的够了!
|
存储 算法 Java
equals 和 hashCode 到底有什么联系?
写在前面 Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码。equals()和hashCode()都不是final方法,都可以被重写(overwrite)。
equals 和 hashCode 到底有什么联系?