HashSet中关于hashCode()和Equals()

本文详细介绍了Java中的HashSet数据结构,它基于HashMap实现,允许存储null值但仅限一个。HashSet添加元素时通过计算元素的hashCode并进行位运算找到存储位置,如果已有元素存在则通过equals方法判断是否相同。在Java 8中,当链表达到一定长度时,会转换为红黑树以提高效率。同时,文章强调了覆盖equals方法时,务必同时覆盖hashCode方法以确保正确性。
摘要由CSDN通过智能技术生成

HashSet


HashSet说明

  1. HashSet实现了Set接口

  2. HashSet底层是HashMap

     private transient HashMap<E,Object> map;//(HashSet的私有属性) 
     
    //这是HashSet构造器,另几个重载的构造器也是创建了HashMap实例对象
    public HashSet() {
      map = new HashMap<>();
    }
    //HashSet的add方法
    public boolean add(E e) {
      return map.put(e, PRESENT)==null;
    }
    
    
  3. 可以存放null值,但是只能有一个null值。

  4. HashSet取出是无序的,因为存储是在计算Hash值后,在确定索引位置,而遍历是顺序遍历。

  5. 不能有重复元素.

  6. 遍历:使用迭代器或增强for循环(实际上还是调用的迭代器),不能使用普通for循环,因为没用提供get方法。

HashSet存储过程

  1. 添加一个元素时,先计算其Hash值,转换成索引值,hash值是根据hashCode值位运算得到的。
static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//右移16位尽量减小碰撞
    }
 //Object提供的hashCode根据元素的地址值返回一个int型整数   

  1. 找到存储数据表table(链表数组),看这个索引位置是否有元素。

  2. 如果没有,直接加入。

  3. 如果有,调用equals方法比较(equals方法一般需要自己编写制定比较规则,若不
    写,则提供默认,默认比较的是地址值),如果相同,则放弃添加,不相同则加到末尾。

  4. Java8中,如果一条链表元素到达默认数:8, 并且table大小>=64,则会进行树化(红黑树);

详细请查看源码或韩顺平Java基础P522—P525。

覆盖Equals方法一定先覆盖hashCode方法

先看JDK1.8文档解释:


在这里插入图片描述

举个例子:

class person{
    String name;
    int age;
}

若覆盖了person类中的Equals方法,让判断两个对象是否相等的条件从比较地址值(系统默认提供的equals方法)转变成比较name和age是否相等,若相等则判定对象相等。而此时若不覆盖hashCode方法,则继续按照系统默认提供的比较,那么根据地址值返回的hashCode值必然不同,那么直接判定为不同而走不到equals方法这一步。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值