1、为什么需要HashMap

前面我们说了ArrayList和LinkedList,它们对容器内的对象都能实现增、删、改、查、遍历等操作,

并且对应不同的情况,我们可以选择不同的List,用以提高效率。从功能上来说,这个容器已经设计得很好了,

为什么我们还要HashMap呢?接下来,让我们细细地分析:

在程序中,我们最常用的动作就是存数据和取数据,存数据就是把数据存起来(包括插入数据和增加数据),

取数据就是找到我们存进去的数据(查找数据),下面从这两个方面来分析一下ArrayList和LinkedList的问题。

  • ArrayList在增加数据和按下标获取数据效率高。
  • LinkedList在插入数据和删除数据方面效率比较高。

提出问题:能不能有一种容器能在它存数据的时候很快,查找数据的时候也很快呢?

新的需求:事物之间都是有关联的。ArrayList是靠下标来关联数据的,这种关联太单一了,

无法完美的适应OO编程环境,面向对象编程就是要把世间万物都用对象包装起来,

我们把这些对象都只与数字(0、1、2)关联起来,也太单调了,也太没有颜色了。

世间是多彩的,基于这种情况,我们就提出:

能不能使其他的事物也与我们的对象关联起来呢?(比如说,我们用汽车牌号码关联汽车,用身份证号码关联人)

当然同时满足上面提出的条件(能不能有一种容器能在它存数据的时候很快,查找数据的时候也很快呢?),

那就非常完美了。

程序袁的回答:是的,我们能过设计出这种容器,他将马上风靡全球。

2、HashMap实现原理

先看看下面这两张图

表1这是HashMap的两种存储模式表二

下面解释这两种表存储对象的原理

首先理解两个概念:

  • hashcode(散列码):现在只需要知道hashcode是返回一个整数。

后面会单独用一章具体解析hashcoed和equal的问题,以及怎么写hashcode和equal的。

  • equal(相等):现在只需要知道equal在两个逻辑上面相等的对象的时候返回true,

例如:new student(1,"aa");和new student(1,"aa")是两个相等的对象,如果用object里面的equal来判断

这两个对象结果是不相等的。

存储数据的分析:

现在有以下几个对象:

a=newnew student(1,"aa"); b=new
student(4,"aa");

c=new
student(2,"aa");d=new student(1,"aa")

现在假设a对象的hashcode是5,b的hashcode是17,假设 c的hashcode是10,,

因为一些规则的原因(在hashcode这一章会重点解析),d的hashcode必须是5;接下来我们就对

这些数据进行存储。先对表一进行存储:int index=hashcode()%12--------这个12是值这个表的大小。

先存a,那么a对象放在5这个位置,接下来存b,此时经过int
index=hashcode()%12,

也会存储到5这个位置,但是此时此刻,5这个位置已经有数据了,,接下来判断这个a对象

跟b对象是否相等,现在是不想等,那我们就把这个b对象放到右边这个非常小的格子里面的第一个格子,

接下来存储c对象,把c放在10这个地方,再接下来存储d,经过计算吗,d会存储到5这个位置,

但是此时此刻,5这个位置已经有数据了,接下来判断这个a对象跟b对象是否相等,现在是相等,

那我们就把d这个对象替换掉原来a的对象。

存储结果如下图:

注意5这个位置的元素的替换

接下来对表二的存储方式进行分析:公式也是一样的int index=hashcode()%12,先存a,那么a对象放在5这个位置,

接下来存b,此时经过int index=hashcode()%12,也会存储到5这个位置,但是此时此刻,

5这个位置已经有数据了,接下来判断这个a对象跟b对象是否相等,现在是不想等,

那我们就把这个b对象放在5这个位置接在a的对象后面,接下来存储c对象,把c放在10这个地方,

再接下来存储d,经过计算吗,d会存储到5这个位置,但是此时此刻,5这个位置已经有数据了,

接下来是遍历5这一条链路的数据,看看是否有相等的对象,现在找到a这个对象是相等的,

那我们就把d这个对象替换掉原来a的对象。存储结果如下图。

注意5这个位置a和d的替换

查找数据的分析:

以上是存储对象时的分析,接下来是查找对象的分析,(以下分析是针对表一进行分析的)现在我要查找三个对象,

x=newnew
student(1,"aa"), y=newnew student(3,"aa"),z=new
student(4,"aa"),

由相等的对象必须有相同的hashcode这个条件的限制(先不管为什么有这个霸道的条件,后面会解析),

我们可知x的hashcode的为5,z的hashcode为17,y的hashcode我们就随便取一个,假设为10,

(为什么不同的对象会有相同的hashcode?这样行吗?合理吗?后面会解析)。接下来我们就来查找对象了。

先查找x,经过int
index=hashcode()%12计算,是第5格,此时有数据,接下来判断这两个对象是否相等,

此时相等,那么我们就找到了这个对象。接下来查找y,经过int
index=hashcode()%12计算是第10个,

此时有数据,接下来判断这两个对象是否相等,此时不相等,然后就到右边那个

非常小的格子里面一个一个的判断是否相等,我们遍历一遍后,发现没有相等的,此时我们得出结论,没有这个数据,

再接下来找z,经过int
index=hashcode()%12计算是第10个,此时有数据,接下来判断这两个对象是否相等,此时不相等,

然后就到右边那个非常小的格子里面一个一个的判断是否相等,在遍历的时候,

我们发现第一个就是相等的,那我们就找到了这个数据。

3、总结HashMap的主要特点

    • 如果我们不知道下标,相比ArrayList和LinkedList,hashMap有具有非常快的查找能力
    • hashMap不仅能够形成键值对,这个是一个非常好的关系

java容器HashMap原理的更多相关文章

  1. 理解java容器底层原理--手动实现HashMap

    HashMap结构 HashMap的底层是数组+链表,百度百科找了张图: 先写个链表节点的类 package com.xzlf.collection2; public class Node { int ...

  2. Java基础-hashMap原理剖析

    Java基础-hashMap原理剖析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.什么是哈希(Hash) 答:Hash就是散列,即把对象打散.举个例子,有100000条数 ...

  3. java中HashMap原理?

    参考:https://www.cnblogs.com/yuanblog/p/4441017.html(推荐) https://blog.csdn.net/a745233700/article/deta ...

  4. Java学习----HashMap原理

    1.HashMap的数据结构 数组的特点是:寻址容易,插入和删除困难:而链表的特点是:寻址困难,插入和删除容易.那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的, ...

  5. 容器HashMap原理(学习)

    一.概述 基于哈希表的 Map 接口的非同步实现,允许使用 null 值和 null 键,不保证映射的顺序 二.数据结构 HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体:Has ...

  6. 理解java容器底层原理--手动实现HashSet

    HashSet的底层其实就是HashMap,换句话说HashSet就是简化版的HashMap. 直接上代码: package com.xzlf.collection2; import java.uti ...

  7. 深入理解Java容器——HashMap

    目录 存储结构 初始化 put resize 树化 get 为什么equals和hashCode要同时重写? 为何HashMap的数组长度一定是2的次幂? 线程安全 参考 存储结构 JDK1.8前是数 ...

  8. java的HashMap 原理

    https://www.cnblogs.com/chengxiao/p/6059914.html 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比 ...

  9. 理解java容器底层原理--手动实现LinkedList

    Node java 中的 LIinkedList 的数据结构是链表,而链表中每一个元素是节点. 我们先定义一下节点: package com.xzlf.collection; public class ...

随机推荐

  1. MFC命名规范

    属性部分 全局变量:g_ 常量:c_ c++类成员变量:m_ 静态变量:s_ 类型部分 指针:p 函数:fn 无效:v 句柄:h 长整型:l 布尔:b 浮点型(有时也指文件):f 双字:dw 字符串: ...

  2. windows下安装apache zookeeper

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的功 ...

  3. 定制自己的new和delete:operator new 和 operator delete

    new和delete不同用法 基本用法 int * aptr = new int(10); delete aptr, aptr = nullptr; 上面的代码是我们最基本也是最常见的使用new和de ...

  4. SVN使用过程中遇到的一些问题

    更新svn的客户端TortoiseSVN后 ,之前使用svn管理的文件的关联图标消失了 说明:下面的解决方法及图片来自博客:装了SVN,你的关联图标变了没有? 解决办法:在同步的文件点击右键如下图   ...

  5. .NetCore下使用Autofac做 IOC 容器

    在.NetCore中使用自带的IOC容器 写注入的时候会写很多,如果要自己封装的话也达不到预期的效果,所以这里采用Autofac来时替代 .NetCore自带的容器 nuget首先引用Autofac. ...

  6. Linux系统运维笔记(二),Linux文件编辑命令

    Linux系统运维笔记 Linux文件编辑命令 首先我们使用命令 vi filename 打开一个文件,这个时候进入到的是命令模式 接下来我们按i,然后键盘随便输入写内容. 然后按ESC重新进入到命令 ...

  7. Angular 5项目

    Angular 5项目 如果您正在使用angular, 但是没有好好利用angular cli的话, 那么可以看看本文. Angular CLI 官网: https://github.com/angu ...

  8. P1540 机器翻译 模拟

    题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 题目描述 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件会先 ...

  9. DFT,DTFT,DFS,FFT区别

        学习了数字信号处理之后,被里面的几个名词搞的晕头转向,比如DFT,DTFT,DFS,FFT,FT,FS等,FT和FS属于信号与系统课程的内容,是对连续时间信号的处理,这里就不过多讨论,只解释一 ...

  10. Qt5编译oracle驱动教程

    我们都知道oracle数据库的强大,并且好多企业或者教学用到数据库时都会推荐使用.但是Qt因为版权问题没有封装oracle数据库专用驱动,网上也有一大堆说法和教程,但是或多或少的都有问题.下面废话不多 ...