HashMap与Hashtable

来源:互联网 发布:冷漠没有同情心知乎 编辑:程序博客网 时间:2024/05/20 16:36

HashMap与HashTable区别,及其原理

结论

1.HashMap对象的key、value值均可为null(而且键只能有一个为null)。
2.HahTable对象的key、value值均不可为null。
3.两者的的key值均不能重复,若添加key相同的键值对,后面的value会自动覆盖前面的value,但不会报错。
4.hashtable是线程安全的,而HashMap不是。

1. Map

所有元素以键值对的形式进行存放,其中键不能重复。(这里可以把键理解为下标,而下标不能重复)

2. HashMap的底层实现

要搞清楚HashMap的底层实现,首先要清楚:hash算法、hash表、hashcode方法。(如果清楚可直从2.4开始看)。

2.1 hash算法

  • hash:
    • 1.hash就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出值就是hash值(也叫做散列值)。
    • 2.该转换是一种压缩映射,即hash值的空间远小于输入值的空间。而且不同的输入值,有可能映射为相同的hash值(这种情况称之为hash碰撞)。所以不能通过hash值来唯一确定输入的值。

2.2 hash表

hash表也称为散列表。hash表也是一种不同于数组、链表、二叉树的数据结构。它能够很快的定位要查找的记录,而不是采用遍历的方式去逐一遍历表中的记录。
现有如下表格数据:

姓名电话peng113688888888peng213699999999peng313677777777peng413666666666

现在要找到peng2的手机号

  • 查找方式一:
    • 从表头开始逐一遍历去查找。直到匹配到与关键字peng2相同的记录为止。
  • 查找方式二:
    • 利用hash表的特性,根据peng2关键字直接匹配到peng2记录所在的地址,得到手机号。

2.3 hashcode方法

直接参考javaAPI文档中有关于Object的hashcode方法的详细介绍。需要注意的是,java 中新new出来的对象,不管类型是否一致,其hashcode方法在没有重写之前的返回的hash值是不同的。

2.4 HashMap的工作原理

HashMap的数据结构是基于数组和链表的。

对于 HashMap 及其子类而言,它们采用 Hash 算法来决定集合中元素的存储位置。当系统开始初始化 HashMap 时,系统会创建一个 Entry 数组,这个数组里可以存储元素的位置被称为“桶(bucket)”,每个 bucket 都有其指定索引,系统可以根据其索引快速访问该 bucket 里存储的元素。每一bucket里面只有一个元素也就是一个Entry对象(理解为键值对对象)。

链表是什么?有两个不同的键,如果根据hashcode方法计算出来的hash值(通过hash值来找到其bucket)相同时,为了区分他们,会在Entry对象里面有一个引用变量指向下一个Entry对象(这个是先放入该bucket中的,也就是所最先储存到bucket中的元素会存在链表的最末端),以此来区分它们。如果多个不同的键,计算出相同的hash值时,就会形成Entry链。
该结构图来源于他人博客文章最后会给出地址
(该结构图来源于他人博客文章最后会给出地址)
HashMap基于hashing原理,通过put()和get()方法来储存和获取对象。

  • get()
    • 首先通过键调用其hashcode()方法获得hash值,在Entry数组中直接找到该键的hash值对应Entry对象的位置,从而根据Entry对象得到键对应的值。
  • put()
    • 首先通过键调用其hashcode()方法获得hash值,在Entry数组中直接找到该键的hash值对应的位置(即bucket),再储存该键对应的值。在存储数据的时候如果发生hash碰撞(也就是通过该键计算出来的hash值的相同)那么会在Entry对象中储存一个引用变量指向下一个Entry(注意最先放入bucket中的Entry对象,会存在于链表的最末端),从而形成Entry链。

关于Entry对象,bucket等概念可参考以下博客。文中的HashMap的结构图也来自该博客。
博客地址

原创粉丝点击