java中哈希家族底层原理

发布时间:2024年01月23日

HashSet如何判断两个对象是否相等?

在Java中,HashSet是使用哈希表实现的,其核心是通过对象的哈希码来快速查找和判断元素是否存在。在判断两个对象是否相等时,HashSet并不直接比较对象的内容,而是通过比较它们的哈希码来快速做出决策。

在Java中,对象相等性的判断有两个条件:

  1. 两个对象引用指向同一个对象(即他们是同一个对象)。
  2. 两个对象引用指向不同的对象,但这两个对象的内容相等。

对于第一个条件,可以通过比较两个引用是否完全相同(即使用“==”操作符)来判断。而对于第二个条件,则需要通过实现equals()方法来定义如何判断两个对象的内容是否相等。

当我们在HashSet中添加或查找元素时,HashSet首先会计算对象的哈希码,然后使用这个哈希码来决定将对象存储在哈希表的哪个位置。然后,如果我们需要查找一个元素,HashSet会计算这个元素的哈希码,并查看该位置的元素是否与我们要查找的元素相等。这个“相等”的判断也是通过equals()方法来实现的。

所以,对于HashSet来说,它并不直接比较对象的每一个属性是否都相同,而是通过比较对象的哈希码来快速判断两个对象是否可能相等。如果两个对象的哈希码不同,那么它们肯定不相等;如果两个对象的哈希码相同,HashSet才会进一步调用equals()方法来最终确定它们是否相等。

请注意,如果你想在HashSet中使用自定义对象,并且这些对象需要根据某些特定属性来判断相等性(例如,你想把表示同一个人的两个不同的实例视为相等的),那么你需要确保你的自定义类正确地覆盖了equals()hashCode()方法。

HashMap的底层实现是什么?

HashMap 是 Java 集合框架中的一种数据结构,它使用哈希表(Hash Table)作为其底层实现。哈希表是一种数据结构,它通过将键(key)映射到桶(bucket)中来存储数据。

在 HashMap 中,每个键值对(key-value pair)都存储在一个节点(Node)中,该节点包含键、值和指向下一个节点的指针。HashMap 使用哈希函数将键映射到桶的索引,这样就可以快速定位到特定的键值对。

HashMap 的底层实现主要包括以下几个方面:

  1. 数组和链表:HashMap 使用一个数组来存储桶,每个桶中包含一个链表,链表中的节点存储了键值对。当发生哈希冲突时,即两个键的哈希值相同,它们会被存储在同一个桶中的链表中。
  2. 哈希函数:HashMap 使用一个哈希函数来将键映射到桶的索引。默认情况下,HashMap 使用对象的 hashCode() 方法来计算哈希值。
  3. 扩容和缩容:当 HashMap 中的元素数量过多或过少时,会进行扩容或缩容操作。扩容是指增加桶的数量,缩容是指减少桶的数量。
  4. 重新哈希:当发生哈希冲突时,HashMap 会使用链表来存储冲突的键值对。当链表过长时,会进行重新哈希操作,即改变哈希函数,使得更多的键能够映射到不同的桶中,从而减少冲突。

总之,HashMap 的底层实现主要包括数组、链表、哈希函数、扩容、缩容和重新哈希等机制。这些机制共同协作,使得 HashMap 能够在常数时间内完成插入、删除和查找操作。

Hashtable和ConcurrentHashMap之间有什么区别?

Hashtable和ConcurrentHashMap是Java中的两种常用的线程安全的Map数据结构,它们之间存在以下主要差异:

  1. 线程安全性:两者都提供了线程安全,但ConcurrentHashMap的线程安全性更强。在Hashtable中,当多个线程同时访问时,需要同步处理,这可能导致性能下降。而ConcurrentHashMap使用了更细粒度的锁,使得在多线程环境下提供了更好的性能和可靠性。
  2. 锁的粒度:在Hashtable中,整个表是加锁的,这可能导致锁竞争激烈,降低并发性能。而ConcurrentHashMap则是将整个哈希表划分为多个小的段(Segment),每个段包含了若干个键值对(Entry)。当多个线程同时访问哈希表时,它们可以同时访问不同的段,从而避免了锁竞争,大大提高了并发度和性能。
  3. 扩容策略:在Hashtable中,一旦触发扩容操作,就需要持有锁的线程完成整个扩容过程。这个过程涉及到大量的元素拷贝,效率较低。而ConcurrentHashMap的扩容操作则是化整为零,扩容时新旧空间同时存在。后续的线程也会执行上述操作,直到将所有元素全部搬运完毕。由于每次只需要拷贝少量元素,效率较高。
  4. 计算hash值方式:在Hashtable中,通过计算key的hashCode()来得到hash值,这个值就是最终的hash值。而在ConcurrentHashMap中,当出现hash冲突时,会通过链表+红黑树的方式解决。此外,ConcurrentHashMap还有一个hash方法重新计算了key的hash值,因为hash冲突变高,所以通过一种方法重算hash值的方法:这里计算hash值,先调用hashCode方法计算出来一个hash值,再将hash与右移16位后相异或,从而得到新的hash值。
  5. 性能:ConcurrentHashMap在很多方面都优于Hashtable。例如,ConcurrentHashMap的size属性通过CAS更新(较快),而Hashtable的size属性通过synchronized操作更新(较慢)。

综上所述,与Hashtable相比,ConcurrentHashMap提供了更高的并发性和更好的性能。在大多数情况下,应该优先选择ConcurrentHashMap作为线程安全的Map实现。

文章来源:https://blog.csdn.net/huaairen/article/details/135723527
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。