euqals和hashCode与Set集合

Object中的equals和hashCode方法

Object类:上帝之泪,所有的类都会继承Object;

Object中的equals方法和“==”号一样,比较的是对象在栈内存中的地址值。

其他的比如String类等引用数据类型集成Object的时候重写了equals方法,比较的是堆内存中的值是否相等。

问题:为什么自定义对象的时候重写equals方法,需要同时重写hashCode方法?

Object中的hashCode方法是根据对象在内存中的地址通过哈希算法计算出哈希值。

当对象重写了equals方法的时候,比较两个对象的值是否相等,根据hashCode规则,如果两个对象相等那么他的哈希值一定是相等的。如果不重写hashCode,两个对象在的内存地址一定不相等,那么两个哈希值永远不会相等。

简单来说:同时需要重写hashCode是为了满足hashCode规则,保证两个对象相等,他的哈希值一定也相等。

ps

hashCode规则:

两个对象相等,哈希值相等。

两个对象不相等,哈希值有可能相等。

哈希值相等,对象不一定相等。

哈希值不相等,对象一定不相等。

附上JDK文档中的解释:

1. 无论何时在执行Java应用程序时多次调用同一对象, hashCode方法必须始终返回相同的整数,前提是修改了对象中equals比较中的信息。 该整数不需要从一个应用程序的执行到相同应用程序的另一个执行保持一致。 

2. 如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。 

3. 不要求如果两个对象根据equals(java.lang.Object)方法不相等,则在两个对象中的每一个上调用hashCode方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能。

Set集合

目前,只看HashSet和LinkedHashSet

HashSet的底层数据结构是 哈希表

LinkedHashSet的底层数据结构是 链表+ 哈希表

哈希表的原理解析:

从两个方面来研究哈希表的结构。

  1. 哈希表查询数据

JDK 1.7 哈希表是由数组 + 链表组成的

JDK 1.8 之后 哈希表是有 数组 + 链表 + 红黑书组成的 。 大大的加强了元素的查找速度。

哈希表: 本质上是一个数组,默认的容量是16;

哈希桶: 数组的每一个索引位置;

哈希桶的数据结构就是链表,而我们知道链表的特点就是查询慢,增删快。所以,在JDK 1.8 以后为了提高查询的速度,当链表长度超过 8 之后自动转换成红黑树。
  1. 哈希表存储数据

哈希表是怎样存储数据的呢?存储在哪里?

这个时候就用到了从Object类中继承的hashCode方法,存储对象的时候hashCode方法会用对象的内存地址根据哈希算法计算出哈希值。然后根据哈希值决定放在哪一个哈希桶中。

equals方法判断是否是同一个对象来决定是否存储进Set集合。

当不同对象存储到了同一个哈希桶中,这就是哈希冲突。(如何解决哈希冲突,请自行百度)

当存储数据的时候,哈系桶的使用数量达到了负载因子(百分之75),哈希表将自动扩容。

总结:当我们用HashSet或者LinkedHashSet来存储数据的时候,hashCode和equals方法是保证存储元素不重复的所在。这个时候,如果我们存储的是自定义的对象的时候,我们必须要重写上帝之泪Object类中的hashCode和equals,否则,集合中的元素可能就会重复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值