要想知道一个元素是否在数组或链表中,只能从前向后挨个对比,无论是数组还是链表,其对数据的查询表现都比较无力。在的二叉排序树中,还会将数据排序以进行二分查找,将时间复杂度从O(n)降低到O(lg n)。

出现这个问题的根源在于,我们没有办法直接根据一个元素找到它存储的位置。

那有没有办法消除这个对比的过程呢?哈希表就是解决查询问题的一种方案。

什么是哈希表与Hash函数

通俗来讲,哈希表就是通过关键字来获取数据的一种数据结构,它通过把关键字映射为表中的位置来获取元素,这种映射主要是使用Hash函数。

因为不同需求需要的key类型不一致,可能是int,可能是String,也可能是其他任意对象。但是内存地址却不能以这些对象来寻址,因而Hash函数的作用就是把这些对象通过合理的方式转为int类型,从而完成数据的存储。Hash函数需要保证的是对于相同的key,其计算结果总是相同的。

这个过程就好比我们用拼音查字典。如果要查一个字,我们不会从第一页到最后一页挨着看,这将需要很长的时间,而是根据其发音先在拼音表中找到对应的页数,直接定位到对应的页即可。当然,由于有许多发音一致的汉字,所以我们可能依然需要逐个对比,但这复杂度就小太多了。

哈希表的过程就和上述例子一致,我们根据元素的key,通过hash函数直接定位其位置。然而类似于许多汉字的发音一致一样,也会有许多的key通过hash函数定位的结果一致,这就是发生了所谓的哈希碰撞。

解决哈希碰撞的方法

比较通用的方法,就是使用数组+链表组合的方式。当出现哈希碰撞时,在该位置的数据就通过链表的方式链接起来,如图所示:

在JDK1.7及之前的版本中,HashMap的存储结构和上图是一致的,在JDK1.8之后还加入了红黑树以进一步优化。

哈希表的优缺点

哈希表是一种优化存储的思想,具体存储元素的依然是其他的数据结构。

设计良好的哈希表,能同时兼备数组和链表的优点,它能在插入和查找时都具备良好的性能。

设计不好的哈希表,有可能会出现较多的哈希碰撞,导致链表过长,从而哈希表会更像一个链表。还有当数据量很大时,为防止链表过长,就需要对数组进行扩容,这时就涉及到了数组的拷贝,其对性能的影响也很严重。

所以需要提前对可能的情况有良好的预测,才能真正发挥哈希表的优势。

源码:Java集合源码之:哈希表(二)的更多相关文章

  1. Java集合(八)哈希表及哈希函数的实现方式

    Java集合(八)哈希表及哈希函数的实现方式 一.哈希表 非哈希表的特点:关键字在表中的位置和它之间不存在一个确定的关系,查找的过程为给定值一次和各个关键字进行比较,查找的效率取决于和给定值进行比较的 ...

  2. Java集合源码分析(四)Vector<E>

    Vector<E>简介 Vector也是基于数组实现的,是一个动态数组,其容量能自动增长. Vector是JDK1.0引入了,它的很多实现方法都加入了同步语句,因此是线程安全的(其实也只是 ...

  3. Java集合源码分析(三)LinkedList

    LinkedList简介 LinkedList是基于双向循环链表(从源码中可以很容易看出)实现的,除了可以当做链表来操作外,它还可以当做栈.队列和双端队列来使用. LinkedList同样是非线程安全 ...

  4. Java集合源码分析(二)ArrayList

    ArrayList简介 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线 ...

  5. Java集合源码学习(一)集合框架概览

    >>集合框架 Java集合框架包含了大部分Java开发中用到的数据结构,主要包括List列表.Set集合.Map映射.迭代器(Iterator.Enumeration).工具类(Array ...

  6. Java 集合源码分析(一)HashMap

    目录 Java 集合源码分析(一)HashMap 1. 概要 2. JDK 7 的 HashMap 3. JDK 1.8 的 HashMap 4. Hashtable 5. JDK 1.7 的 Con ...

  7. java集合源码分析几篇文章

    java集合源码解析https://blog.csdn.net/ns_code/article/category/2362915

  8. java集合源码分析(三):ArrayList

    概述 在前文:java集合源码分析(二):List与AbstractList 和 java集合源码分析(一):Collection 与 AbstractCollection 中,我们大致了解了从 Co ...

  9. java集合源码分析(六):HashMap

    概述 HashMap 是 Map 接口下一个线程不安全的,基于哈希表的实现类.由于他解决哈希冲突的方式是分离链表法,也就是拉链法,因此他的数据结构是数组+链表,在 JDK8 以后,当哈希冲突严重时,H ...

  10. Java集合(九)哈希冲突及解决哈希冲突的4种方式

    Java集合(九)哈希冲突及解决哈希冲突的4种方式 一.哈希冲突 (一).产生的原因 哈希是通过对数据进行再压缩,提高效率的一种解决方法.但由于通过哈希函数产生的哈希值是有限的,而数据可能比较多,导致 ...

随机推荐

  1. jQuery.ready() 函数详解

    jQuery.ready() 函数详解 ready()函数用于在当前文档结构载入完毕后立即执行指定的函数. 该函数的作用相当于window.onload事件. 你可以多次调用该函数,从而绑定多个函数, ...

  2. 使用VUE框架搭建项目基本步骤

    ps:初入Vue坑的小伙伴们,对于独立做一个项目可能不清楚需要使用哪些资源,这篇随笔希望对大家有所帮助. 第一步:参照vue的官方文档,建立一个vue的项目 # 全局安装 vue-cli $ npm ...

  3. 为什么会出现container、injection技术?发展历史及未来发展趋势

    container 原因: 随着软件开发的发展,相比于早期的集中式应用部署方式,现在的应用基本都是采用分布式的部署方式,一个应用可能包含多种服务或多个模块,因此多种服务可能部署在多种环境中,如虚拟服务 ...

  4. SQL Update 语句详解

    SQL Update 语句详解   Update 语句 Update 语句用于修改表中的数据. 语法: UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值 Person: L ...

  5. K2在Gartner 2017 iBPMS魔力象限报告中上升为“挑战者”

    在Gartner近期发布的iBPMS MQ报告中,Gartner分析了入选的19家厂商,将K2列为智能业务流程管理系统(iBPMS)MQ(魔力象限)的“挑战者”.从下列图中可以看出,相比上期,K2从魔 ...

  6. JsonLayout log4j2 json格式输出日志

    如果日志输出时,想改变日志的输出形式为Json格式,可以在log4j2.xml中使用JsonLayout标签,使日志输出格式为Json格式. 前提需要Jackson的包,保证项目中包含jackson的 ...

  7. manjaro配置

    manjaro配置 Table of Contents manjaro配置 系统 一.初次使用 二.安装软件 输入法 emacs samba 三.配置修改 konsole shell颜色 系统 man ...

  8. python读取与写入csv,txt格式文件

    python读取与写入csv,txt格式文件 在数据分析中经常需要从csv格式的文件中存取数据以及将数据写书到csv文件中.将csv文件中的数据直接读取为dict类型和DataFrame是非常方便也很 ...

  9. windows下telnet不是内部或外部命令

    选择“程序和功能” 设置完后

  10. TensorFlow 算术运算符

    TensorFlow 算术运算符 TensorFlow 提供了几种操作,您可以使用它们将基本算术运算符添加到图形中. tf.add tf.subtract tf.multiply tf.scalar_ ...