编程语言
首页 > 编程语言> > Java编程思想——第17章 容器深入研究 读书笔记(四)

Java编程思想——第17章 容器深入研究 读书笔记(四)

作者:互联网

九、散列与散列码

HashMap使用equals()判断当前的键是否与表中存在的键相同。

正确的equals()方法需满足一下条件:

1)自反性。x.equals(x) 是true;

2)对称性。x.equalse(y) 返回true y.equals(x)也得是true;

3)传递性。x.equals(y) 返回true ,y.equals(z) 返回true , x.equals(z)返回true;

4)一致性。如果对象中用于等价比较的信息没有变,那么无论多少次 x.equals(y)返回值不会变

5)x.equals(null) 返回 false ;注意:(null).equals(x)报空指针。

强调:默认的Object.equals()只比较对象的地址,因此如果使用自己的类作为HashMap的Key,必须同时重载hashCode()和equals()。

hashCode()并不需要总是能够返回唯一的标识码,但是equals()方法必须严格的判断两个对象是否相等,作为键必须唯一否则系统报错。

    @Override
    public boolean equals(Object o) {
        return o instanceof T && (i.equals(((T) o).i)));
    }

instanceof检查了此对象是否为null ,是null则返回false。

为速度而散列

以线性查询的是最慢的查询方式,存储一组元素最快的数据结构是数组,所以使用它来标识键的信息(注意,这里说的是键信息不是键本身)。

由于数组不能调整容量,所以数组不保存键本身,而是通过键对象生成一个散列码,将其作为数组的下标,这个散列码就是由Object中的、或自己的类覆盖的hashCode()生成的。

数组固定的问题解决了,但是键可以产生相同的下标,也就是说可能会有冲突。数组多大不重要,任何键总能在数组中找到它的位置。

于是,查询一个值的过程首先就是计算散列码,然后使用散列码查找数组。如果能够保证没有冲突(如果被查询的值的数量是固定的,就有可能)。

通常,冲突由外部链接处理;数组并不直接保存值,而是保存值的list。然后对list中的值使用equals()方法进行线性查询。

这部分查找会比较慢,但是如果散列函数好的话,数组每个位置就有较少的值。

因此,不是查询整个List而是快速的跳转到数组的某个位置,只对很少的元素进行比较。这就是HashMap会如此快的原因。 

我们把散列表的数组称为bucket(桶),为了散布均匀且速度快,桶的容积通常使用质数或者2的整数次方,用LinkedList填充桶。

put()操作,计算key的hashCode(),找到桶中的位置,看LinkedList内容,有值用equals()与值的key相比,相等就替换,不等或者没有值就在尾部加上新值。

覆盖hashCode()

桶下标值是无法控制的,这个值依赖于具体的HashMap对象的容量,而容量的改变与容器的充满程度和负载因子有关。hashCode()生成的结果,经过畜栏里后成为桶位的下标。

Joshua Blochw指出为写出一份像样的hashCode给出了知道:

1)给 int 变量 result 赋予某个非0常量,

2)为对象内每个有意义的域f(既每个可以做equals()操作的域)计算一个int 散列码 c:

域类型:                                                                 计算:

boolean                                                                   c=(f?0:1)

byte、char、short、int                                           c=(int)f

float                                                                         c=(int)(f^(f>>>32))

double                                                                     long I =Double.doubleToLongBits(f); c=(int)(I^(I>>>32))

Object,其equals()调用这个域的equals()       c=f.hashCode()

数组                     对每个元素应用上述规则   

3)合并计算得到散列码

result = 37*result+c                         

 

 

标签:Java,17,读书笔记,int,equals,hashCode,数组,散列码,true
来源: https://www.cnblogs.com/xcgShare/p/11718155.html