zoukankan      html  css  js  c++  java
  • Java HashMap和Hashtable的原理和区别

    1、概述:HashMap 基于哈希表<key,value>,实现Map接口,接受null的键和值,不允许重复的key,但允许重复的value,即不同的key可以对应相同的value值,非线程安全,Hashtable和HashMap非常类似,同样实现了Map接口,但是Hashtable不接受null的键和值,Hashtable是线程安全的,Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

    2、数据结构:数组和链表的结合。本身是一个数组,数组中的元素是链表。如图所示:

    数组中存储的是链表的头结点,元素存储到数组中的规则是:一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。

    HashMap和Hashtable里面有一个静态内部类Entry,其重要属性包括key,value,next,从这些属性就可以看出这是对键值对实现的一个基础bean,所以HashMap和Hashtable是一个线性数组Entry[]

    3、存数据

    键值对A,通过计算key的hash值得到index,则该元素存储在Entry[index],当有键值对B获得的index相同时,上面我们提到过Entry类里面有一个next属性,作用是指向下一个Entry,所以HashMap会这样做:B.next = A,Entry[index] = B,如果又进来C,index也相同,那么C.next = B,Entry[index] = C,数组中存储的是最后插入的元素(注:HashMap和Hashtable里面设置一个加载因子,随着map的size越来越大,Entry[]会根据加载因子以一定的规则加长长度。)

    4、取元素,先根据key值获取到键值对在数组中的下标,然后再遍历该下标处的链表。

    5、null key总是存放在Entry[]数组的第一个元素。

    6、HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。

    注:“快速失败”也就是fail-fast,它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,有可能会产生fail-fast机制。记住是有可能,而不是一定。例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast机制。

  • 相关阅读:
    整理了一份React-Native学习指南
    新建项目
    spring security 匿名登录
    spring security remember me实现自动登录
    spring security为不同用户显示各自的登录成功页面
    spring security 管理会话 多个用户不可以使用同一个账号登录系统
    spring security 图解过滤器的使用
    spring security 判断用户是否登录 只要登录就可以访问资源
    spring security动态管理资源结合自定义登录页面
    spring security自定义拒绝访问页面
  • 原文地址:https://www.cnblogs.com/mingyao123/p/6907136.html
Copyright © 2011-2022 走看看