文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

HashMap底层原理分析

2023-06-27 16:34

关注

小编给大家分享一下HashMap底层原理分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

众所周知,HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干

HashMap底层原理分析

1. 特性

我们可以用任何类作为HashMap的key,但是对于这些类应该有什么限制条件呢?且看下面的代码:

public class Person {   private String name;   public Person(String name) {       this.name = name;   }}Map testMap = new HashMap();testMap.put(new Person("hello"), "world");testMap.get(new Person("hello")); // ---> null

本是想取出具有相等字段值Person类的value,结果却是null。对HashMap稍有了解的人看出来——Person类并没有override hashcode方法,导致其继承的是Object的hashcode(返回是其内存地址),两次new出来的Person对象并不equals——这也是为什么在工程项目中常用不变类(如String、Integer等)做为HashMap的key的原因。那么,HashMap是如何利用hashcode给key做索引的呢?

2. 原理

首先,我们来看《Thinking in Java》中一个简单HashMap的实现方案:

//: containers/SimpleHashMap.java// A demonstration hashed Map.import java.util.*;import net.mindview.util.*;public class SimpleHashMap extends AbstractMap { // Choose a prime number for the hash table size, to achieve a uniform distribution: static final int SIZE = 997; // You can't have a physical array of generics, but you can upcast to one: @SuppressWarnings("unchecked") LinkedList>[] buckets =   new LinkedList[SIZE]; public V put(K key, V value) {   V oldValue = null;   int index = Math.abs(key.hashCode()) % SIZE;   if(buckets[index] == null)     buckets[index] = new LinkedList>();   LinkedList> bucket = buckets[index];   MapEntry pair = new MapEntry(key, value);   boolean found = false;   ListIterator> it = bucket.listIterator();   while(it.hasNext()) {     MapEntry iPair = it.next();     if(iPair.getKey().equals(key)) {       oldValue = iPair.getValue();       it.set(pair); // Replace old with new       found = true;       break;     }   }   if(!found)     buckets[index].add(pair);   return oldValue; } public V get(Object key) {   int index = Math.abs(key.hashCode()) % SIZE;   if(buckets[index] == null) return null;   for(MapEntry iPair : buckets[index])     if(iPair.getKey().equals(key))       return iPair.getValue();   return null; } public Set> entrySet() {   Set> set= new HashSet>();   for(LinkedList> bucket : buckets) {     if(bucket == null) continue;     for(MapEntry mpair : bucket)       set.add(mpair);   }   return set; } public static void main(String[] args) {   SimpleHashMap m =     new SimpleHashMap();   m.putAll(Countries.capitals(25));   System.out.println(m);   System.out.println(m.get("ERITREA"));   System.out.println(m.entrySet()); }}

SimpleHashMap构造一个hash表来存储key,hash函数是取模运算Math.abs(key.hashCode()) % SIZE,采用链表法解决hash冲突;buckets的每一个槽位对应存放具有相同(hash后)index值的Map.Entry,如下图所示: HashMap底层原理分析 JDK的HashMap的实现原理与之相类似,其采用链地址的hash表table存储Map.Entry:

transient Entry[] table = (Entry[]) EMPTY_TABLE;static class Entry implements Map.Entry {   final K key;   V value;   Entry next;   int hash;   …}

Map.Entry的index是对key的hashcode进行hash后所得。当要get key对应的value时,则对key计算其index,然后在table中取出Map.Entry即可得到,具体参看代码:

public V get(Object key) {   if (key == null)       return getForNullKey();   Entry entry = getEntry(key);   return null == entry ? null : entry.getValue();}final Entry getEntry(Object key) {   if (size == 0) {       return null;   }   int hash = (key == null) ? 0 : hash(key);   for (Entry e = table[indexFor(hash, table.length)];        e != null;        e = e.next) {       Object k;       if (e.hash == hash &&           ((k = e.key) == key || (key != null && key.equals(k))))           return e;   }   return null;}

可见,hashcode直接影响HashMap的hash函数的效率——好的hashcode会极大减少hash冲突,提高查询性能。同时,这也解释开篇提出的两个问题:如果自定义的类做HashMap的key,则hashcode的计算应涵盖构造函数的所有字段,否则有可能得到null。

看完了这篇文章,相信你对“HashMap底层原理分析”有了一定的了解,如果想了解更多相关知识,欢迎关注编程网行业资讯频道,感谢各位的阅读!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯