• 集合框架(十)----HashMap


    关于HashMap的继承体系,可以查看上一篇博文!

    然后,是时候(装逼了)展现真正的技术了:

    首先我们打开Map<K,V>接口瞅瞅,发现接口中除了定义了一大坨规范外啥都没有!于是我们接着打开AbstractMap<K,V> 看看,大致猫一眼后:几个常用方法的实现都很简单啊,没意思!接着当然是打开传说中的HashMap<K,V>了!!!

    首先截张图压压惊:

    什么?这么多?这怎么读?不知道你怕不怕,反正我是怂了!虽然怂了,但不能放弃啊(哥可是个有始有终的人)!于是,我们从关键部分开始,尽量学到其核心部分,其他的就暂时不用管了!

    一个类的开始的核心部分当然是构造方法了,然后聪明的我找到了构造方法中最核心的一个构造方法:

    图中我标出了几个关键点,这个构造方法中有两个参数,分别是初始容量加载因子

    那么,问题来了。What 初始容量and加载因子???下图是来自jdk1.6的注释文档的解释:

    至于这两货的默认值,可在源码的开头部分容易的找到!

    然后,还有一个不认识的玩意:`this.threshold = tableSizeFor(initialCapacity);`

    于是,ctrl+鼠标左键(本人用的eclispe。idea,NetBean都是这个快捷键)找到这个方法:

    瞅了瞅,不就是位运算吗?有啥了不起,对不对!但是,为什么要这么做呢?虽说会位运算,但毕竟用的少,不是很熟悉,而且还有或运算,不知道你能不能看懂,反正我是完全懵逼了!但是,不知道它的原理,得知道它的用途啊,要不然没办法继续啊!看到我标出的那段英文注释了吗?这就是大神给我们这些菜鸟的解释!大致意思是:返回一个接近参数一个2的n次方数

    虽说看完了构造方法,但构造方法中仅仅是确定了对象的加载因子初始容量,这两货到底有啥用啊?HashMap到底怎样存储数据啊?迷雾重重啊!那接下来该读哪里呢?当然是put方法了!为什么?你在使用HashMap时,第一步创建一个HashMap类的实例对象;第二步是干什么??当然是。。。嗯,没错,让我们看看传说中的put方法

    What???Lets ctrl+鼠标左键:

    真TMD长,这里不得不说两句,写这部分源码的作者竟然把表的初始化和键值的添加放在一起,看到红色框框的那句判断了吗?你每次添加一组值,便要进行一次判断,简直卧槽!分开写多好啊,像前面List的实现都是在构造方法中初始化的!

    然后看看用红色圈圈圈起来的东西,我们ctrl+鼠标左键

    很显然,这货是用来存储元素的!并用覆写了hashCode()方法!看到这个Node有没有想到什么??我可是想到了很多呢,比方说:Linked

    怎么样?是不是很像呢!没错,就是链表!

    接下来,让我们认识认识那个令人讨厌的resize()方法

    看到没,因为没有单独初始化,所以在这里还要判断!看到我标出的注释了吗!大致意思是:`初始化或让容量加倍`

    先看看怎么初始化的:

    然后再瞅瞅如何使容量增大:

    大致思路就是,容量变为原来的2倍,然后将旧表中的数据都复制到新表中!

    然后看看如何添加键值(突然发现这个方法真TMD流弊):

    看到这个不知道你有没有想到什么,我可是又想到了好多东西呢,比方说:

    没错,邻接表,像不像,像不像!但是,从get()方法来看,人家的下标取值是这样的:

    高大上啊,有没有!完全懵逼啊!懵逼就懵逼吧!毕竟高大上!

    那么,HashMap的核心思路大致就是这些了!里面还是有不少东西没有搞懂,待研究!

  • 相关阅读:
    ERROR: epmd error for host "yourhostname": timeout
    leetcode485
    leetcode463
    leetcode496
    leetcode344
    leetcode412
    leetcode500
    leetcode476
    leetcode557
    leetcode461
  • 原文地址:https://www.cnblogs.com/realsoul/p/5903279.html
Copyright © 2020-2023  润新知