欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > 数据结构与算法-【算法专项】Hash算法-2(HashMap+设计Hash+Hash应用+Hashmap常用方法)

数据结构与算法-【算法专项】Hash算法-2(HashMap+设计Hash+Hash应用+Hashmap常用方法)

2025/9/7 4:28:19 来源:https://blog.csdn.net/yinying293/article/details/139941685  浏览:    关键词:数据结构与算法-【算法专项】Hash算法-2(HashMap+设计Hash+Hash应用+Hashmap常用方法)

数据结构与算法-Hash算法-2

  • 5 HashMap(又双叒叕提到红黑树动态扩容)
  • 6 如何设计Hash
  • 7 Hash的应用
  • 8 HashMap源码(又双叒叕)
    • 构造方法:
    • put方法:
    • get方法:
    • equals方法:
    • containsKey方法:
    • values方法:
    • entrySet方法:
    • hash方法(用于自定义对象作为键时):

5 HashMap(又双叒叕提到红黑树动态扩容)

由于链表这种结构确实存在一些缺点,所以在我们的JDK中对之进行了优化,引入了更高效的数据结构:红黑树

  1. 初始大小:HashMap默认的初始大小是16,这个默认值是可以设置的,如果事先知道大概的数据量有多大,可以通过修改默认初始大小,减少动态扩容的次数,这样会大大提高HashMap的性能。

  2. 动态扩容:最大装载因子默认是0.75,当HashMap中元素个数超过0.75*capacity(capacity表示散列表的容量)的时候,就会启动扩容,每次扩容都会扩容为原来的两倍大小。

  3. Hash冲突解决办法:JDK1.7底层采用链表法。

    在JDK1.8版本中,为了对HashMap做进一步优化,我们引入了红黑树。而当链表长度太长(默认超过8)时,链表就转换为红黑树。我们可以利用红黑树快速增删改查的特点,提高HashMap的性能。当红黑树结点个数少于8个的时候,又会将红黑树转化为链表。因为在数据量较小的情况下,红黑树要维护平衡,比起链表来,性能上的优势并不明显。

  4. Hash函数:JDK的hash函数非常经典,建议大家收藏,以后都可以用。

    int hash(Object key) {int h = key.hashCode()return (h ^ (h >>> 16)) & (capitity -1); //capicity表示散列表的大小,最好使用2的整数倍
    }
    

6 如何设计Hash

假如你在面试中碰到了要你如何设计一个高效的企业级Hash表。你该如何处理?

这里大家可以借鉴HashMap 的设计思路:

  1. 必须要高效:即插入,删除 查找必须要快
  2. 内存:不能占用太多的内存,考虑用其他的结构,比如B+Tree,HashMap 10亿,存硬盘的算法:mysql B+tree
  3. Hash函数:这个要根据实际情况考虑.%
  4. 扩容:就是预估数据的大小,HashMap 默认的空间是16? 我知道我要存10000个数,2^n > 10000 or 2^n-1
  5. Hash冲突后怎么解决:链表 数组。

7 Hash的应用

  1. 加密:MD5 哈希算法。还是存在密码冲突 128位的二进制串,可以表示2^128次,md5(md5(),”1231”),b不可逆,建了一个hash库,存起来了。 Md5(88888888),穷举

  2. 怎么判断视频是否是重复的?Md5();128位

  3. 相似性检测:论文检测,指纹算法。会把每个论文计算出一个指纹,汉明距离。

  4. 负载均衡:nginx,2台服务器;可以根据ip计算hash,再做一个取模2运算。

  5. 分布系统:数据分库问题。我不是讲过一个10亿的数据的搜索词,一台机器存不下。要分成10个文件。Hash(key)%10 = > 就可以知道某个key在哪一个文件?扩大成数据库的 分表(10张表) id%10 =()。

  6. 分布式存储的时候:问题来了 如果我加了一张表。原来是10张,现在是11张了 怎么办?要重新计算,分配的时候查询怎么办?数据量很大,迁移的不是太多了吗?

  7. 查找算法:hashMap 查找如何设计出自己的一个hash查找算法呢?快,hash冲突要少,数据大小。初始大小,扩容

  8. 一致性Hash:哈希环

    假设我们有k个表,数据的hash值范围:[0,Integer.max].我们把整个数据范围划分成n个区间(n个区间要远远大于我们的k),每一个表就是分配到n/k的区间。当有新的表要来了,我们只需要将某几个小的区间数据迁移就可以了。这是一个环形结构,其根本思想就是分段了。

重点部分:数组 链表 二叉树 红黑树 HashMap源码

8 HashMap源码(又双叒叕)

HashMap是Java集合框架中的一个重要类,用于存储键值对。

HashMap的一些核心常用方法的简要说明和示例代码,具体细节可能涉及到哈希碰撞、加载因子、扩容等实现细节,这些通常不需要开发者手动实现,但了解这些细节有助于更好地理解HashMap的工作原理。

  1. 构造方法:

    HashMap<Integer, String> map = new HashMap<>(); // 创建一个空的HashMap
    HashMap<Integer, String> mapWithCapacity = new HashMap<>(16); // 创建一个预设容量的HashMap
    
  2. put方法:

    map.put(1, "Apple"); // 添加键值对
    
  3. get方法:

    String value = map.get(1); // 获取键对应的值
    
  4. equals方法:

    在Java中,HashMapequals方法用于比较两个HashMap对象是否相等。equals方法首先会检查两个对象的hashCode是否相等,如果hashCode不等,那么两个对象不可能相等,如果hashCode相等,那么HashMap会进一步比较其中的元素。

    以下是HashMapequals方法的核心代码:

    public boolean equals(Object o) {if (o == this)return true;if (!(o instanceof Map))return false;Map<?,?> m = (Map<?,?>) o;if (m.size() != size())return false;try {Iterator<Entry<K,V>> i = entrySet().iterator();while (i.hasNext()) {Entry<K,V> e = i.next();K key = e.getKey();V value = e.getValue();if (value == null) {if (!(m.get(key)==null && m.containsKey(key)))return false;} else {if (!value.equals(m.get(key)))return false;}}} catch (ClassCastException unused) {return false;} catch (NullPointerException unused) {return false;}return true;
    }
    

    这段代码首先检查o是否等于this,如果是,则直接返回true。然后检查o是否是一个Map实例。如果不是,则直接返回false。如果是,HashMap会比较其大小,如果两个Map的大小不等,则直接返回false。接下来,HashMap会迭代其所有的Entry,并逐一检查o中是否包含相同的键值对。如果有任何一个键值对不匹配,则返回false。如果所有的键值对都匹配,则返回true

    这个方法是HashMap对象相等性的核心实现,它确保了两个具有相同键值对的HashMap被认为是相等的。

  5. remove方法:

    String removedValue = map.remove(1); // 移除键值对并返回值
    
  6. size方法:

    int size = map.size(); // 获取HashMap的大小
    
  7. isEmpty方法:

    boolean isEmpty = map.isEmpty(); // 检查HashMap是否为空
    
  8. containsKey方法:

    boolean contains = map.containsKey(1); // 判断HashMap是否包含键1
    
  9. containsValue方法:

    boolean containsValue = map.containsValue("Apple"); // 检查HashMap中是否包含指定值
    
  10. keySet方法:

    Set<Integer> keySet = map.keySet(); // 获取HashMap中所有键的Set视图
    
  11. values方法:

    Collection<String> values = map.values(); // 获取HashMap中所有值的Collection视图
    
  12. entrySet方法:

    Set<Map.Entry<Integer, String>> entrySet = map.entrySet(); // 获取HashMap中所有键值对的Set视图
    
  13. clear方法:

    map.clear(); // 清空HashMap中的所有键值对
    
  14. hashCode方法:

    Collection<String> values = map.values(); // 获取HashMap中所有值的Collection视图
    
  15. clone方法:

  16. hash方法(用于自定义对象作为键时):

    public class MyKey {int value;// 必须重写hashCode方法@Overridepublic int hashCode() {return Objects.hash(value);}// 必须重写equals方法@Overridepublic boolean equals(Object obj) {if (this == obj) return true;if (obj == null || getClass() != obj.getClass()) return false;MyKey myKey = (MyKey) obj;return value == myKey.value;}
    }
    

    注意:以上代码示例假设IntegerString是键和值的类型,实际使用时可以替换为任何实现了equals()hashCode()方法的对象。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词