浅谈浅谈HashSet底层实现原理

HashSet底层实现原理

在这里插入图片描述

  • 当然Hashset是基于HashMap实现 的,下面来看一下它的构造方法
//Constructs a new, empty set; 
//the backing HashMap instance has default
// initial capacity (16) and load factor (0.75). 
public HashSet() {
        map = new HashMap<>();
    }

上面注释的意思就是:默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。

  • 往HashSet集合中放入元素 ,会调用add()方法,实际上是放到了HashMap(存储的是key-vakue)中的key中
   public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

可以看到add()方式实际上也是调用了构造方法中的构建的map对象中的 put()方法 。

大家都知道HashMap中存储的是键值对的形式,那为什么HashSet能使用HashMap 的put()方法呢?

​ 其实是 所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。

点击PRESENT进去后会发现

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();
  • 当我们想使用HashMap和HashSet存储一个类的对象时,必须要重写该类的==equals()方法和 hashCode() 方法,但是存储一个int 类型的元素时,我们不需要重写Integer类的equals()==方法和 hashCode() 方法。是因为Integer中已经重写的这两个方法,

  • 如果要放入一个你自己写的类,那一定要重写这个类的==equals()==方法和 hashCode() 方法。

  • 那为什要重写这两个方法呢?

  • 首先我们要知道HashSet不能存入重复的元素。如果不重写会不会违背这个条件呢?

    public static void main(String[] args) {
    		HashSet<Student> set2 = new HashSet<Student>();
    		set2.add(new Student("ccc",15));
    		set2.add(new Student("aaa",14));
    		set2.add(new Student("ccc",15));
    		set2.add(new Student("bbb",21));
    		for(Student i:set2) {
    			System.out.println(i.getName()+"---"+i.getAge());
    		}
    	}
    //结果
    ccc---15
    ccc---15
    bbb---21
    aaa---14
    	
    

    接下来就验证了面的猜想。因为自己定义的Student没有重写这两个方法,所以存入了重复的值。
    在这里插入图片描述

  1. 先说说为什么重写hashcode?

1.1 首先进入add
在这里插入图片描述
1.2 接着进入put方法
在这里插入图片描述
1.3 接着进入putVak方法
在这里插入图片描述 此处可以看到HashSet在进行添加底层使用到了hash方法,而hash值的获取实际上是在hashCode基础上的一系列操作,如果不重写hashcode,用的则是从Object继承下来的hashCode,而这个hashCode每次new一个对象就会有不同的值;所以就造成了上面的student中的即使 内容一样 但还是被认为是不同的元素,因为每次存入时 都是new了一个新对象,就造成了hash值一直不同。

  1. 接下来说为什么重写equals?

对于自定义类需要手动实现hashCode,当判断hash值一致后还会调用equals再次进行检测,判断内容是否一致;

为什么还要用equals比较呢?

因为hash值毕竟只是一个逻辑值,不同的对象有几率出现相同的hash值(称为哈希碰撞)。如果不同的对象出现了相同的hash值就需要使用equals进行再次判断

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

圆○

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值