- 在Java中,散列表用链表数组实现.每个列表被称为
桶
.(见下图).要想查找表中对象的位置,就要先计算它的散列码,然后与桶的总数取余,所得到的结果就是保存这个元素的桶的索引.例如,如果某个对象的散列码为76268.并且有128个桶,对象应该保存在第108号桶中(76268除以128余108).或许会很幸运,在这个桶中没有其他元素,此时将元素直接插入桶中就可以了.当然,有时候会遇到桶被占满的情况,这也是不可避免的.这种现象被称为散列冲突
.这时,需要用新对象与桶中的所有对象进行比较,查看这个对象是否已经存在.如果散列码是合理且随机分布,桶的数目也足够大,需要比较的次数就会很少.
在Java1.8中,桶满时会从链表变为平衡二叉树.如果选择的散列函数不当,会产生很多冲突,或者如果有恶意代码试图在散列表中填充多个有相同散列码的值,这样就能提高性能.
- 如果想更多地控制散列表的运行性能,就要指定一个初始的桶数.桶数是指用于收集具有相同散列值的桶的数目.如果要插入到散列表中的元素太多,就会增加冲突的可能性,降低运行性能
- 如果大致知道最终会有多少个元素要插入到散列表中,就可以设置桶数.通常,将桶数设置为预计元素个数的75%~150%.有些人认为,尽管没有确凿证据,但最好将桶数设置为一个素数,以防键的集聚.标准类库使用的桶数是2的幂,默认值为16.
- 当然,并不是总能够知道要存储多少个元素的,也有可能最初的估计过低.如果散列表太满,就需要再散列.如果要对散列表再散列,就需要创建一个桶数更多的表,并将所有元素插入到这个新表中,然后丢弃原来的表.
装填因子
决定何时对散列表进行再散列.例如,如果装填因子为0.75(默认值),而表中超过75%的位置已经填入元素,这个表就会用双倍的桶数自动地进行再散列.对于大多数程序来说,装填因子为0.75是比较合理的.
HashMap装填因子为啥默认0.75?
最新推荐文章于 2022-12-30 16:33:12 发布