Java - 散列码

散列与散列码

正确的equals()方法必须满足以下5个条件:
1. 自反性.对任意x,x.equals(x)一定返回true.
2. 对称性.对任意x/y,如果y.equals(x)返回true,则x.equals(y)也返回true
3. 传递性.对任意x/y/z,如果有x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)一定返回true.
4. 一致性.对任意x/y,如果对象中用于等价比较的信息没有改变,那么无论如何调用x.equals(y)多少次,返回的结果应该保持一致,那么一直是true,要么一直是false
5. 对任何不是null的x,x.equals(null)一定返回false.

Object.equals()只是比较对象的地址

如果想用自己的类作为HashMap的键,必须同时重载hashCode()和equals()

instanceof会偷偷检查左侧的对象是否为null,如果位null,则返回false

理解hashCode()

散列的目的在于:想要使用一个对象来查找另一个对象.

瓶颈的原因在于查询速度.

散列将键的信息保存在某处,以便能快速找到(数组是存储元素最快的数据结构).通过键对象生成一个数字,将其作为数组的下标,这个数字就是散列码,由散列函数(Object.hashCode())生成.

为了解决数组容量被固定的问题,不同的键可以产生相同的下标.也就是说可能会有冲突,因此数组多大也就不重要了,任何键都能在数组中找到他的位置.

查询一个值的过程首先就是计算散列码,然后使用散列码查询数组,如果能够保证没有冲突(如果值的数量是固定的,那么就有可能冲突),那么就有了一个完美的散列函数.

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

如果散列函数比较好,数组的每个list就会有比较少的值.

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

由于散列表中的”槽位 slot”通常称为捅位(bucket),为了使散列均匀分布,桶的数量通常使用2的整数次方,因为除法和求余是最慢的操作,可以用掩码来替代.

覆盖hashCode()

  1. 给int变量result赋予某个非零值常量
  2. 为对象内有意义的域(即每个可以做equals()的域)计算出一个int散列码c
  3. 合并计算的得到的散列码 result = 31 * result + c;
  4. 返回result
域类型计算
booleanc = f ? 0 : 1
byte/char/short/intc = (int)f;
longc = (int)(f ^ f>>>32)
floatc = Float.floatToInBits(f);
doublelong l = Double.doubleToLongBits(f); c = (int)(l ^ (l>>>32));
Objectc = f.hashCode();
数组对每个元素应用应用以上规则

性能

可以手工调整HashMap来提高性能:
1. 容量:桶位数
2. 初始容量:在创建是所拥有的捅位数.HashMap和HashSet都允许设置.
3. 尺寸:表中当前存储的项数.
4. 负载因子:尺寸/容量.空表的负载因子是0,而半满的负载因子是0.5.负载轻的表,出产生冲突的可能性小,对于插入和查找都是最理想的.
HashMap和HashSet都允许指定负载因子,当达到负载因子的水平时,容器将自动增加其容量(桶位数),实现方式是容量大致加倍,并重新将现有的对象分部到新的捅位中,称之为再散列.
A`
HashMap使用的负载因子是0.75(只有当表达到四分之三时,才进行散列),这个因子在时间和空间代价中达到了平衡,更高的负载因子可以降低表所需的空间,但是会增加查找的代价.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值