有关hashCode实现的细节

开发过程中,当自己创建的类没有重写Object的hashCode()方法时,那么对象在散列集合中的操作,将默认使用Object的hash算法,即与对象内存地址有关的本地方法返回的数值,这样导致一些实例域相同的对象最终比较结果却是不同的。

那么,如果想要实现自己的hashCode方法,如何实现比较好呢。

在方法中可以使用Objects.hashCode()方法,来生成域的散列码,将各个域的散列码通过与素数相乘再通过自己定义的运算组成产生新的哈希码,如(((属性one哈希码 * 31)+属性two哈希码) * 31)以此类推,将生成一个依赖属性1和属性2的顺序和值的哈希码,至于为啥是31,好像是根据大神科学家们的统计使用31出现相同的哈希冲突频率最低。反之如下定义hashcode则两个属性互换值也将产生相同的哈希值。

public class ObjectTest {
    private String name;
    private String local;

    public ObjectTest(String name,String local) {
        this.name=name;
        this.local=local;
    }

    public static void main(String[] args) {
        System.out.println(new ObjectTest("a","b").hashCode()==new ObjectTest("b","a").hashCode());
    }
    public int hashCode() {
        return name.hashCode()*31+local.hashCode()*31;
    }
}

或者hash(Object… values)更为方便。

hash()方法:

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;
    }

那么element的hashCode方法返回的是什么呢?

常见的String类型的hashCode方法:

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

如果自己定义的类中包含基本类型的属性,那么element.hashCode()是什么呢?

其实会调用包装类的hashCode方法

Integer:

private final int value;
@Override
    public int hashCode() {
        return Integer.hashCode(value);
    }


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

Double:

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


    public static int hashCode(double value) {
        long bits = doubleToLongBits(value);
        return (int)(bits ^ (bits >>> 32));
    }

Character:

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


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

Boolean:

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


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

另外,如果自己定义的hashCode返回的哈希值依赖于一些容易变化的属性,那么往HashSet中add一个对象后,对象属性改变,则无法通过Set接口的contains方法确定是否集合中存在该对象。代码如下:

public class CollectionTest {
    private String field;
    public CollectionTest(String field) {
        this.field=field;
    }
    @Override
    public int hashCode() {
        return field.hashCode();
    }
    public void setField(String field) {
        this.field=field;
    }
    @Override
    public String toString() {
        return field;
    }

    public static void main(String args[]) {

        //Set
        Set<CollectionTest> set = new HashSet<>();
        CollectionTest test =  new CollectionTest("a");
        set.add(test);
        test.setField("b");
        System.out.println(set.contains(test));
        set.add(test);
        System.out.println(set.toString());
    }
}

结果如下:

false
[b, b]

转载于:https://my.oschina.net/u/3902438/blog/2244649

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值