浅析hashMap原理及简单实现

HashMap是一种基于哈希表的数据结构,用于存储键值对,其中键是唯一的。哈希函数用于确定元素的存储位置,但可能导致哈希冲突。解决冲突的策略包括线性探测、二次探测和链地址法(开散列)。Java中的HashMap采用了数组+链表+红黑树的方式,当链表长度超过8时,会转为红黑树提高效率。
摘要由CSDN通过智能技术生成

知识补充

hashMapMap的具体实现类。Map是一个接口类,该类没有继承自Collection,该类中存储的是键值对,并且键唯一,不能重复。

键值对就是一个唯一的key对应一个值。举个例子:就像学生的学号,每个学生的学号对应一个同学的姓名,学号是唯一的,学生的姓名可以重复。也就是说,键值对中键唯一,一个键对应一个值,但是也可以有多个键对应相同的值。就像学校有多个叫王五的同学,他们的学号唯一,但是对应的姓名都是王五。

在这里插入图片描述

注意

  • Map是一个接口,不能实例化对象。如果要实例化对象只能实例化其实现类
  • Map中的键是唯一的,value是可以重复的
  • 在Map中插入键值对,键不能为空,值可以为空
  • Map中键值对的key不能直接修改,value可以直接修改,如果要修改key,只能先将key删除掉再插入

hashMap概念

在顺序结构和二叉搜索树中,元素与其位置没有一一对应的关系,因此在查找一个元素时,必须要经过比较遍历。顺序查找的时间复杂度为O(n),二叉搜索树和二分查找为O(logn),搜索的效率取决于元素比较的次数。

理想的搜索方法就是:不经过任何比较,依次从表中找到想要的元素。如果能构造一种存储结构,通过某种函数使元素的存储位置和元素之间能够建立起对应的关系,那么在查找时,就可以很快找到该元素。

该方法即为哈希(散列)方法,哈希方法中使用的转换函数为称为哈希函数,构造出来的结构称为哈希表

存储方式:

  • 插入元素

    根据插入元素的关键字,使用哈希函数来计算出该元素的存储位置,并按此位置存放

  • 查找元素

    对元素的关键字进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置比较,若关键字相等,则找到该元素

例如集合:{1,8,4,9,2,3,5}

哈希函数设置为:hash(key) = key % capacity,capacity为存储元素底层空间的大小

在这里插入图片描述

假设哈希表的默认存储容量为10,那么我们按照哈希函数hash(key) = key % capacity来得出每一个关键字存储的位置,并将关键字放进去。同样取数据时,我们知道key,就可以用哈希函数找到存储key的位置,然后找到该元素。然而,按照如上方式继续插入19时,就会发现9号地址已经有关键字。此时该怎么做?扩容?然后放到下标为19的地址吗?

哈希冲突

我们发现,对于两个不同的关键字key,使用哈希函数计算之后得到了相同的地址,这种现象称为哈希冲突。这种冲突如何避免呢?单纯的扩容肯定是不行的,假如集合元素为{9,19,29,39,49,59}难道为了存储这几个数据去开60的空间吗?

冲突避免–哈希函数设计

我们需要明确的是,哈希表底层数组的容量往往是小于我们实际要存储的关键字的数量的,意思就是哈希冲突的发生是必然的,我们要想办法尽量降低冲突率

引起哈希冲突原因:哈希函数设计不合理

哈希函数的设计原则

  • 哈希函数的定义域必须要包括全部的关键字,如果哈希表允许有m个地址时,其值域必须在0到m-1之间
  • 哈希函数计算出的地址能均匀分布在整个存储空间
  • 哈希函数应该比较简单

常见哈希函数

  1. 直接定制法

    取关键字的某个线性函数为散列地址:hash(key) = A*key + B

    优点:简单、均匀 缺点:需要事先知道关键字的分布情况

    例如:字符串中的第一个唯一字符

    使用哈希表的思想,我们知道字母有26个,创建大小为26的字符数组,通过哈希函数char - 'a'得到key的地址(下标),遍历过程中,每出现一次相同的key就让chars[char - 'a']地址的值加一。然后我们得到了第i个字母在字符串中出现的次数即chars[i],最后遍历字符串,找chars[char - 'a']位置的值是否为1,遇到的第一个为1的即返回结果。

        public int firstUniqChar(String s) {
         
            char[] chars = new char[26];
            for(char c : s.toCharArray()<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值