数据结构篇09、哈希表--简化版HashMap(1)

本文详细描述了基于数组和红黑树的哈希表实现,包括添加、移除元素的操作过程,以及扩容和resize函数的工作原理。作者还介绍了查找和修改元素的方法。
摘要由CSDN通过智能技术生成

2、往哈希表中添加元素

通过hash函数计算元素的数组索引,通过此索引在hashtable数组中找到TreeMap,如果此key已存在map中,那么直接覆盖,如果不存在,直接添加到map中;而此map的底层实现是红黑树,所以我们的哈希表的底层实现可以认为是数组加红黑树的实现;

添加完元素检查是否需要扩容,扩容思想就是自增capacityIndex索引,然后去capacity数组中找对应的素数即可,这样保证了每次扩容后容量都是一个对应哈希表数据规模的素数;

resize函数也非常简单,新建一个TreeMap数组,将原map数组中所有值复制到新数组,复制的过程有几个需要注意的点,先保存一下原数组的大小,再将M赋值为新数组的大小,为什么需要这么做?因为第一层for循环需要遍历的是原数组的大小,而第二层foreach循环求元素在新数组的hash值时需要使用新数组的大小;最后将hashtable引用指向新的数组;

public void add(K key, V value){
TreeMap<K, V> map = hashtable[hash(key)];
if(map.containsKey(key))
map.put(key, value);
else{
map.put(key, value);
size ++;

if(size >= upperTol * M && capacityIndex + 1 < capacity.length){
capacityIndex ++;
resize(capacity[capacityIndex]);
}
}
}

private void resize(int newM){
TreeMap<K, V>[] newHashTable = new TreeMap[newM];
for(int i = 0 ; i < newM ; i ++)
newHashTable[i] = new TreeMap<>();

int oldM = M;
this.M = newM;
for(int i = 0 ; i < oldM ; i ++){
TreeMap<K, V> map = hashtable[i];
for(K key: map.keySet())
newHashTable[hash(key)].put(key, map.get(key));
}

this.hashtable = newHashTable;
}

3、从哈希表中移除元素

首先通过hash函数计算元素在数组中的索引,然后通过此索引去hashtable数组中找对应map,如果map包含此元素,直接从map中删除元素即可;最后检查一下是否需要缩容,原理跟扩容是完全相同的;

public V remove(K key){
V ret = null;
TreeMap<K, V> map = hashtable[hash(key)];
if(map.containsKey(key)){
ret = map.remove(key);
size --;

if(size < lowerTol * M && capacityIndex - 1 >= 0){
capacityIndex --;
resize(capacity[capacityIndex]);
}
}
return ret;
}

4、从哈希表中查找和修改元素

查找和修改的逻辑基本一致,首先通过hash函数计算元素在数组中的索引,然后通过此索引去hashtable数组中找对应map,最后通过map的put函数去修改元素;通过map的containsKey或者get函数去查找元素;

public void set(K key, V value){
TreeMap<K, V> map = hashtable[hash(key)];
if(!map.containsKey(key))
throw new IllegalArgumentException(key + " doesn’t exist!");

map.put(key, value);
}

public boolean contains(K key){
return hashtable[hash(key)].containsKey(key);
}

public V get(K key){
return hashtable[hash(key)].get(key);
}

5、哈希表完整代码

import java.util.TreeMap;

public class HashTable<K extends Comparable, V> {

private final int[] capacity
= {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741};

private static final int upperTol = 10;
private static final int lowerTol = 2;
private int capacityIndex = 0;

private TreeMap<K, V>[] hashtable;
private int size;
private int M;

public HashTable(){
this.M = capacity[capacityIndex];
size = 0;
hashtable = new TreeMap[M];
for(int i = 0 ; i < M ; i ++)
hashtable[i] = new TreeMap<>();
}

private int hash(K key){
return (key.hashCode() & 0x7fffffff) % M;
}

public int getSize(){
return size;
}

public void add(K key, V value){
TreeMap<K, V> map = hashtable[hash(key)];
if(map.containsKey(key))
map.put(key, value);
else{
map.put(key, value);
size ++;

if(size >= upperTol * M && capacityIndex + 1 < capacity.length){
capacityIndex ++;
resize(capacity[capacityIndex]);
}
}
}

public V remove(K key){
V ret = null;
TreeMap<K, V> map = hashtable[hash(key)];
if(map.containsKey(key)){
ret = map.remove(key);
size --;

if(size < lowerTol * M && capacityIndex - 1 >= 0){
capacityIndex --;
resize(capacity[capacityIndex]);
}
}
return ret;
}

public void set(K key, V value){
TreeMap<K, V> map = hashtable[hash(key)];
if(!map.containsKey(key))
throw new IllegalArgumentException(key + " doesn’t exist!");

map.put(key, value);
}

public boolean contains(K key){
return hashtable[hash(key)].containsKey(key);
}

public V get(K key){
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

Android高级架构师

由于篇幅问题,我呢也将自己当前所在技术领域的各项知识点、工具、框架等汇总成一份技术路线图,还有一些架构进阶视频、全套学习PDF文件、面试文档、源码笔记。

  • 330页PDF Android学习核心笔记(内含上面8大板块)

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

  • Android BAT部分大厂面试题(有解析)

好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

试题(有解析)**

[外链图片转存中…(img-ckJbNMdC-1712425636086)]

好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值