HashMap简单入门

0.README

本文首先介绍了每一个对象都继承的hashCode()equals()函数,然后说明HashTable如何利用这两个函数将键值对存入其底层数据结构,最后介绍了重写Key对象的hashCode()equals()compareTo())函数的基本要求。

1.hashCode()equals()函数

java.lang.Object类有两个公共函数hashCode()equals()

int hashCode()方法生成的散列码(hashcode),默认是使用对象的地址计算散列码,即使克隆后的对象,拥有相同的字段,也会具有不同的hashCode()值。这样显然是不合理的,因此通常需要根据字段重写。

boolean equals()方法默认比较两个对象的hashCode()值。Object的子类会重写equals()方法,如String,比较的是字符串内容。

对基于散列的数据结构(HashSet, HashMap, LinkedHashSet, LinkedHashMap)来说,在区分Key时,都是基于HashTable的底层原理,需要同时覆盖这两个方法(原因见第二部分)。例如:

public class Groundhog{
    protected int number;
    public Groundhog(int n){number = n;}
    public int hashCode(){ // 使用字段生成散列码
        return number; 
    } 
    public boolean equals(Object o){ // 比较字段number的值,若o为null,则返回false
         return (o instanceof Groundhog) && (number == ((Groundhog)o).number);
    }
    public String toString(){
        return "Groundhog #" + number;
    }
}


2.HashTable的机理

这里以HashMap存放键值对的过程为例,介绍HashTable。

HashTable底层有两层数据结构,第一层是bucket数组,数组元素是存储键值对的链表结构,第二层就是这个存储键值对的链表结构。(如下图所示)

键值对添加到HashMap容器中时,首先计算Key的散列值(hashCode()),然后根据散列值计算bucket数组下标(桶位),需要注意的是即使散列值不同,仍有可能被分配到同一个桶位。比如一种简单的方式是用hashCode() % bucket.length来计算下标。

键值对进入桶位中的第二层链表结构时,用equals()方法判断Key值是否已近存在量表中,若存在,则用新的Value值取代旧值,若不存在则向链表中添加这个键值对对象。
HashTable底层结构

3.函数重写的基本要求

重写hashCode()函数的基本要求是:

  • 同一对象每一次计算出的散列值都相同。
  • 不同的Key对象,它们地址不同,但如果它们具有相同的有标志意义的字段,应该也保证它们散列值相同,即基于对象的内容生成散列码。
  • 为使bucket数组负载均匀,好的hashCode函数应该产生分布均匀的散列值,不会集中在某一桶位附近。

重写equals()函数,要根据有标志意义的字段唯一确定对象,通常是直接比较这些字段的值。

有的Key需要排序,因此要实现Comparable接口,与equals()类似,在覆盖compareTo()函数时,也要尽量根据有意义的识别内容来比较对象。

参考文献

[1] 《Java编程思想(第4版)》. https://book.douban.com/subject/2130190/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值