栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java 中 HashSet 的底层基本原理实现

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java 中 HashSet 的底层基本原理实现

一:HashSet集合的特点
    底层数据结构是哈希表不能保证存储和取出的顺序完全一致它没有索引,无法使用for循环进行遍历,可以使用迭代器和增强for由于它是Set集合,所以元素唯一。

下面通过代码可以看出上面的特点:

package com.wt.hashset;

import java.util.HashSet;
import java.util.Iterator;

public class HashSetDemo1 {
    
    public static void main(String[] args) {
        HashSet hs = new HashSet();
        hs.add("1");
        hs.add("1");
        hs.add("3");
        hs.add("2");
        hs.add("4");
        //使用迭代器
        Iterator iterator = hs.iterator();
        while (iterator.hasNext()){
            String i = iterator.next();
            System.out.println(i);
        }
        //使用增强for循环
        System.out.println("------------------------------------------");
        for (String s : hs){
            System.out.println(s);
        }

    }
}

二:哈希值介绍

        哈希值是JDK根据对象的地址值或者属性值计算出来的一个int类型的整数

哈希值的特点:
    如果我们没有重写hashCode和equals方法的话,那么就默认调用对象的地址值,来计算哈希值的。同一个对象调用的哈希值,得到的值都是一样的,不同对象不一样如果在标准类中重写了hashCode和equals方法,那么我们就是根据对象的属性来计算的哈希值 。如果不同对象的属性值是一样的,那么我们计算出来的哈希值也是一样的。
哈希冲突:
    由于int类型的取值范围有限,不同对象属性 计算出来的哈希值也有可能相同,所以我们就需要通过equals方法来比较属性是否相同。
package com.wt.hashset;

import com.wt.hashset.domain.Student;

public class HashSetDemo2 {
    
    public static void main(String[] args) {
        Student s1 = new Student("小猪",21);
        Student s2 = new Student("小牛",11);
        //在object中,是根据对象的地址值计算出来的哈希值是int类型的整数
        System.out.println(s1.hashCode());//356573597
        System.out.println(s1.hashCode());//356573597


        System.out.println(s2.hashCode());//1735600054

    }
}
三:哈希表

哈希表:

    Jdk8(不包括8)之前,底层采用数组+链表结构Jdk8开始,进行了优化,由数组+链表+红黑树来实现的
四:HashSet底层原理:

Jdk 1.7 中 HashSet 原理

HashSet hs = new HashSet();
    创建了一个默认长度为16,默认加载因子为0.75的数组,数组名为table。根据元素的哈希值和数组的长度计算出存入的位置(索引)值。判断当前位置是否为null,如果是null,则直接存入如果应存入的位置不是null,表示该位置有元素,则调用equals方法比较属性值。如果属性值一样,则不存入,如果属性值不一样,则存入数组,老元素挂载在新元素下面,形成链表结构。每次存入一个数据都和链表中的元素进行equals比较属性,属性值一样,则不存,不一样则存,重复以上操作。当存满了16个长度的元素怎么办呢?这是一个问题,这个问题就交给了加载因子,我们默认的加载因子是0.75。当数组中存满了 16*0.75 = 12 个元素的时候,数组就会自动扩容为当前数组长度的两倍。

上面就是jdk1.7版本的HashSet集合的底层原理。

如果链表中的元素过多会照成查询效率低下,每一次进行存储都会在链表中一个一个去比较,浪费时间。所以在这里我们要引入Jdk1.8更新的内容。

Jdk 1.8 中 HashSet 底层原理

在上文中我们说到了,jdk1.7中底层的实现原理,还是有一些缺点的,所以我们java在jdk1.8中就进行了改进。

若我们这个链表上挂载了很多元素,每一次进行存储都会在链表中一个一个去比较,对判断的效率影响太大。所以在jdk 1.8 中我们采用了 红黑树的结构。当链表的长度超过8的时候,自动给我们转化成了红黑树。小的元素在右边,大的元素在左边,这样我们进行查询判断的效率就大大的提高了。

 如果HashSet集合要存储自定义对象,那么必须重写hashCode和equals方法

以上就是我对HashSet底层原理的基本理解,希望可以帮助大家,若有不正确的地方,还希望大家指出。

        

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/776930.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号