Java对象的hashcode()方法

本文详细介绍了Java中hashCode方法的基本概念,包括其在哈希表中的作用、重写规则及注意事项。同时,文章对比分析了基本类型与引用类型在hashCode计算上的差异,并提供了实例代码说明equals与hashCode的关系。
一、hashcode简介

注意:
  public int hashCode()方法返回对象的哈希码值。 这种方法是为了散列表,如HashMap。
     第一条: 只要在执行Java应用程序时多次在同一个对象上调用该方法, hashCode方法必须始终返回相同的整数。
     第二条: 如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
     第三条: 不要求如果两个对象根据equals(java.lang.Object)方法不相等,那么在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能,减少哈希碰撞
  由类别Object定义的hashCode方法确实为不同对象返回不同的整数,未重写方法时一般通过将对象的内部地址转换为整数来实现,重写后一般通过将对象的内容转换为整数来实现
   哈希表: 哈希表是结合了直接寻址和链式寻址两种方式,所需要的就是将需要加入哈希表的数据首先计算哈希值,其实就是预先分个组,然后再将数据挂到分组后的链表后面,随着添加的数据越来越多,分组链上会挂接更多的数据,同一个分组链上的数据必定具有相同的哈希值,java中的hash函数返回的是int类型的,也就是说,最多允许存在2^32个分组,也是有限的,所以出现相同的哈希码就不稀奇了


总结:
  1、hashcode相等,equals不一定相等,这也是哈希碰撞产生的原因。
  2、equals相等,若没有重写equals方法,则为同一个对象,其对应的hashcode相等,若重写了equals方法,但是没有重写hashcode方法,则不一定相等,要是重写了hashcode方法则相等。


二、包装类型

  包装类型全都重写了hashcode方法
    1)、Byte、Short、Integer、Long对应的hashcode方法,均是返回原值

        Integer a = 1;
        System.out.println(a.hashCode());//1
        Byte b = 2;
        System.out.println(b.hashCode());//2
        Short d = 3;
        System.out.println(d.hashCode());//3
        Long e = 4L;
        System.out.println(e.hashCode());//4

重写后的方法:Byte、Short、Integer、Long方法类似

  @Override
    public int hashCode() {
        return Short.hashCode(value);
    }
    
    public static int hashCode(short value) {
        return (int)value;
    }

    2)、Character对应的hashcode方法,返回的是字符对应的ASCII码值(包含0-9、a-z、A-Z以及一些字符)

        Character f = '!';
        System.out.println(f.hashCode());//33

重写后的方法

  @Override
    public int hashCode() {
        return Character.hashCode(value);
    }

    public static int hashCode(char value) {
        return (int)value;
    }

    3)、Double、Float对应的hashcode方法,返回的是经过计算的值,与地址无关,也和数据类型无关

        Double g = 2.0;
        System.out.println(g.hashCode());//1073741824
        Double g1 = 2.0;
        System.out.println(g.hashCode() == g1.hashCode());//true
        Float h = 2.0F;
        System.out.println(h.hashCode());//1073741824

重写后的方法

  @Override
    public int hashCode() {
        return Double.hashCode(value);
    }
    
     public static int hashCode(double value) {
        long bits = doubleToLongBits(value);
        return (int)(bits ^ (bits >>> 32));
    }
    
       public static long doubleToLongBits(double value) {
        long result = doubleToRawLongBits(value);
        // Check for NaN based on values of bit fields, maximum
        // exponent and nonzero significand.
        if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
              DoubleConsts.EXP_BIT_MASK) &&
             (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
            result = 0x7ff8000000000000L;
        return result;
    }

    4)、Boolean对应的hashcode方法,返回的是固定的两个值,true返回1231,false返回1237

        Boolean i = true;
        System.out.println(i.hashCode());//1231

重写后的方法

      @Override
    public int hashCode() {
        return Boolean.hashCode(value);
    }

    
    public static int hashCode(boolean value) {
        return value ? 1231 : 1237;
    }
    


二、引用数据类型

  分析实例解释

public class People {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public People() {
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        People people = (People) o;
        return age == people.age &&
                Objects.equals(name, people.name);
    }

    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }
}

        Set<People> set = new HashSet<>();
        set.add(xiaoer);
        set.add(xiaomi);

如果想完整的使用HashSet类那么最少要重写equals()和hashCode()方法。重写hashCode() 用于获得元素的存储位置,重写equals() 用于在两个元素的位置相同的时候比较两个元素是否相等。
重写后的方法。

     @Override
        public int hashCode() {
    
            return Objects.hash(name, age);
        }
    
    
          public static int hash(Object... values) {
            return Arrays.hashCode(values);
        }
    
    
        public static int hashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());

        return result;
    }
    
        People xiaomi = new People("小米",4);
        People xiaoer = new People("小米",4);
        System.out.println(xiaoer.hashCode() == xiaomi.hashCode());//重写后,ture
        System.out.println(xiaoer.hashCode() == xiaomi.hashCode());//重写前,false
    

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值