要想知道一个元素是否在数组或链表中,只能从前向后挨个对比,无论是数组还是链表,其对数据的查询表现都比较无力。在的二叉排序树中,还会将数据排序以进行二分查找,将时间复杂度从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. 【log4j】使用注意事项

    实际过程中,使用log4j遇到的一些问题,进行总结: 1.log4j.properties文件的放置路径: 必须放在src的根目录下,这样就不需要额外的加载了 2.申明一个log对象 Logger l ...

  2. 线程基础:多任务处理——MESI协议以及带来的问题:伪共享

    1.概述 本文和后续文章将着眼CPU的工作原理阐述伪共享的解决方法和volatile关键字的应用. 2.复习CPU工作原理2.1.CPU工作原理要清楚理解本文后续内容,就需要首先重新概述一下JVM的内 ...

  3. python笔记9-字符串操作

    1.定义字符串 字符串有下标从0开始,用[]可以来取下标 2.字符串读取 字符串可以使用循环for,每次取一个取出,循环对象的每个元素 3.字符串修改-字符串不可修改 字符串是不可变变量,一旦定义就不 ...

  4. [SCOI2005]繁忙的都市

    emm...就是个最小生成树板子...我还能说啥... 为啥我早出生个十多年.../(ㄒoㄒ)/~~ 五六年也好啊.../(ㄒoㄒ)/~~ 呆码: #include<iostream> # ...

  5. mybaties逆向工程教程工具

    http://www.cnblogs.com/wangkeai/p/6934683.html

  6. 20175224 2018-2019-2 《Java程序设计》第二周学习总结

    教材学习内容总结 本周对教材的第二第三章进行了学习,通过阅读教材,我发现java和c语言在相似的基础上还是有很多不同的地方,以下是我对这周学习知识的一些总结. 2.1 java标识符中的字母是区分大小 ...

  7. 解决Fiddler查看Post参数中文乱码的问题

    解决Fiddler查看Post参数中文乱码的问题 解决方法: 1.win+R 2.打开注册表编辑器:输入regedit +回车+是 3.HKEY_CURRENT_USER\Software\Micro ...

  8. Alpha冲刺6

    前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/10004107.html 作业博客:https://edu.cnblogs.com/campus ...

  9. msfvenom生成各类Payload命令

    Often one of the most useful (and to the beginner underrated) abilities of Metasploit is the msfpayl ...

  10. centos7.4 分区 格式化

    1. 查看磁盘 [root@yzb-centos72-3 ~]# fdisk -l Disk /dev/vda: 32.2 GB, 32212254720 bytes, 62914560 sector ...