Java集合2.0

6.HashMap的实现原理

HashMap内部维护了一个数组,数组的每个元素称为一个桶,当我们向HashMap中放入一个键值对时,首先会根据key的哈希值计算出这个键值对在数组中的索引位置。当不同的key通过哈希函数计算得到相同的索引位置时,这些键值对会以链表的形式存储在同一个桶中,在java8中,如果链表长度达到一定阈值(默认为8),并且数组长度大于64,这个链表会被转换为红黑树,提高查找效率。

7.哈希冲突的解决方法

1.线性探测法

当发生哈希冲突时,线性探测法会按照一定的顺序,在哈希表中查找下一个空闲的位置来存储冲突的元素;比如哈希函数计算的初始位置是3,如果位置被占用,就会尝试4,5等位置,以此类推直到找到下一个空闲位置。

2.二次探测法

它不是按照顺序以此探测下一个位置,而是按照一个二次函数的方式来探测空闲位置。但是可能出现探测序列的周期性,导致某些位置无法被探测到。

3.双重哈希法

双重哈希法使用两个不同的哈希函数,当发生冲突时,首先使用第一个哈希函数计算出初始位置x,如果该位置被占用,就用第二个哈希函数计算出一个偏移量d,然后按照x+d,x+2d的顺序来探测空闲位置。但是设计两个合适哈希函数比较复杂,需要确保第二个哈希函数产生的偏移量能够遍历整个哈希表,避免出现无法探测的空洞。

4.链地址法

在一个简单的哈希表实现中,有一个数组作为哈希桶,每个桶指向一个链表。当有新元素插入且发生冲突时,就将新元素插入到对应桶所连接的链表的头部或者尾部(取决于具体的实现)。在查找元素时,首先通过哈希函数找到对应的桶,然后在链表中逐个比较元素,直到找到目标元素或者遍历完整个链表确定不存在目标元素。

5.再哈希法

当发生哈希冲突时,使用另一个哈希函数重新计算哈希值,直到找到一个空闲的存储位置。

8.HashMap和Hashtable的区别

1.线程安全性

  • HashMap:非线程安全,在多线程环境下,如果多个线程同时对HashMap进行插入,删除或者修改操作,可能导致数据不一致,死循环等问题。比如在扩容过程中,如果多个线程同时触发扩容操作,可能会导致链表形成环,进而在后续的遍历操作中出现死循环。
  • Hashtable:线程安全,方法基本都被synchronized关键字修饰。

2.null值处理

  • HashMap:允许key为null,但只能有一个key为null。同时允许value为空,这使得在某些应用场景下,如缓存系统中,使用 HashMap 更加灵活,因为可以方便地用 null 值来表示某些特殊状态,比如缓存未命中。
  • Hashtable:不允许key或者value为null,会抛出异常。

3.迭代器一致性

  • HashMap:在迭代器创建后,如果其他线程对 HashMap 进行了结构上的修改(如插入、删除元素),迭代器可能会抛出ConcurrentModificationException异常。这是因为 HashMap 内部有一个modCount变量,用于记录结构修改的次数,当迭代器在运行过程中发现modCount与预期的值不一致时,就会抛出该异常。
  • Hashtable:在迭代器创建后,其他线程对Hashtable进行修改时,不会抛出异常,因为它的迭代器是弱一致性的。

4.初始容量和扩容机制

  • HashMap:默认初始容量为16,负载因子为0.75.当元素个数超过容量*负载因子的适合,会触发扩容操作,新的容量为原来的两倍。
  • Hashtable:默认初始容量为11,负载因子为0.75.扩容时,新的容量是原来的二倍加一。

9.HashMap 和 ConcurrentHashMap 的区别

1.线程安全

ConcurrentHashMap:是线程安全,采用了多种复杂技术来确保在多线程环境下的正确操作,在java7和之前的版本中,它采用了分段锁的机制:将数据分成多个段,每个段类似一个独立的小哈希表,不同段之间的操作可以并发进行,只有在对同一段进行操作时才需要获取到锁,大大提高了并发性能。在java8和以后的版本,它采用了更加细粒度的Node节点所,并且在一些操作大部分情况再时无锁的,进一步提高了并发性能。

HashMap:是非线程安全的。在多线程环境下,当多个线程同时对 HashMap 进行写操作(如putremove)时,数据可能会出现不一致的情况。

2.数据结构

  • HashMap:内部主要是由数组和链表(当链表长度超过一定阈值时会转换为红黑树)构成。它通过计算键(key)的哈希值来确定元素在数组中的位置,当出现哈希冲突时,将元素以链表(或红黑树)的形式存储在相应位置。
  • ConcurrentHashMap:在java7之前,主要由Segment和HashEntry数组构成,segment是一种可重入锁,主要作用是将哈希表分成多段,每个segment是一个独立的哈希表,管理着一个HashEntry数组。hashentry是实际存储键值对的节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值