什么是Hashmap?


HashMap 是一个关联数组、哈希表,它是线程不安全的,允许key为null,value为null。遍历时无序。

在JDK8中,当链表长度达到8,会转化成红黑树,以提升它的查询、插入效率,它实现了Map<K,V>, Cloneable, Serializable接口。

因其底层哈希桶的数据结构是数组,所以也会涉及到扩容的问题。

当HashMap的容量达到threshold域值时,就会触发扩容。扩容前后,哈希桶的长度一定会是2的次方。
这样在根据key的hash值寻找对应的哈希桶时,可以用位运算替代取余操作,更加高效。

数组:      内存中的一片连续区域,同类型数据的集合,有索引,查询快,增删慢,不可扩容。

链表:   不连续的区域,每个节点放值和指向下一个节点的指针。查询慢,增删快

哈希表:  可以理解位数组和链表的组合。即一个一维数组,但是数组中的每个元素是一个链表

HashMap常量:

    1.DEFAULT_INITIAL_CAPACITY    //默认初始化的容量时16,必须是2的幂次方。

    2.MAXIMUM_CAPACITY      //最大容量:最大的容量是2^30。

    3.DEFAULT_LOAD_FACTOR = 0.75f  //默认的负载因子是0.75

    4.TREEIFY_THRESHOLD = 8    //一个桶中bin的存储方式由链表转换成树的阈值。即当桶中bin的数量超过TREEIFY_THRESHOLD时使用树来代替链表。默认值是8

    5.UNTREEIFY_THRESHOLD = 6  //当执行resize扩容操作时,当桶中bin的数量少于UNTREEIFY_THRESHOLD时使用链表来代替树。默认值是6 。

    6.MIN_TREEIFY_CAPACITY     //当桶中的bin被树化时最小的hash表容量

成员变量:

1.transient Node<K,V>[] table; //这个数组在首次使用时初始化,并根据需要调整大小。分配空间时,长度始终是2的幂次方。   

  • table是一个用于存放键值对的数组。
  • 第一次使用(插入元素)时被初始化,根据需要可以重新分配空间(扩容: 因为规定容量是2的幂,所以扩容时把原容量乘2.)。
  • 分配的空间长度必须是2的幂次方。

2.transient Set<Map.Entry<K,V>> entrySet;  //当被调用entrySet时被赋值。通过keySet()方法可以得到Map中的key集合,通过values可以得到Map中的value集合。

3.transient int size;    //该值用于存放Map中键值对的个数。

4.transient int modCount;  //HashMap被结构性修改的次数

5.int threshold;      //阈值,当HashMap中的键值对数量超过了阈值,就会扩容。thresold = capacity * loadFactor

6.final float loadFactor;    //负载因子

 

HashMap共包括4个构造函数:


      public HashMap()// 默认构造函


      public HashMap(int initialCapacity, float loadFactor) / /指定“容量大小”和“加载因子”的构造函数


      public HashMap(int initialCapacity) // 指定“容量大小”的构造函数


      public HashMap(Map<? extends K, ? extends V> m) // 包含“子Map”的构造函数,将m中的全部元素逐个添加到HashMap中

哈希冲突的解决方法:1.开放地址法  2.链地址法  3.公共溢出法  4.再哈希法

 

为什么HashMap线程不安全?

HashMap会进行resize操作,在resize操作的时候会造成线程不安全。

1. put的时候导致的多线程数据不一致  

2. HashMap的get操作可能因为resize而引起死循环

HashMap线程不安全应该怎么解决?

1.使用HashTable替代HashMap  //一个线程访问HashTable的同步方法时,其他线程如果也要访问同步方法,会被阻塞住。

2.类ConcurrentHashMap定义Map  //ConcurrentHashMap是JUC包中的一个类,方法内部使用了synchronized保证线程安全。

3.Collections类的synchronizedMap(Map m)方法可以返回一个线程安全的Map

 

HashMap跟Hashtable的区别?

HashMap 是 Hashtable 的轻量级实现(非线程安全的实现),他们都完成了 Map 接口,主 要区别在于 HashMap 允许空(null)键值(key),由于非线程安全,在只有一个线程访问 的情况下,效率要高于 Hashtable。

1.历史原因:Hashtable 是基于陈旧的 Dictionary 类的,HashMap 是 Java 1.2引进的 Map 接口的一个实现

2.同步性:Hashtable 是线程安全的,也就是说是同步的,而 HashMap 是线程序不安全的, 不是同步的

3.值:只有 HashMap 可以让你将空值作为一个表的条目的 key 或 value


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM