HashMap和TreeMap区别?如何选?

HashMapTreeMap 都是 Java 中实现键值对映射的类,两者在数据结构、顺序性、时间复杂度和线程安全方面存在差异。

二者区别:   

数据结构:

  • HashMap底层实现为哈希表(Hash Table),使用数组和链表/红黑树实现。使用键的 hashCode() 进行计算桶下标,将值存储在对应的桶中。当发生哈希冲突时,会以链表或红黑树的形式将相同 hash 值的元素连接在一起。
  • TreeMap:底层实现为红黑树(Red-Black Tree),是一种自平衡二叉查找树,根据 Key 值进行排序。查找 insert/delete 的时间复杂度为 O(logN)。

排序能力:

  • HashMap不保证 Key-Value 映射的插入顺序与遍历顺序相同。具有随机存取特性,访问元素速度快,适合大规模数据存储,但其存储顺序不能保证恒定
  • TreeMap每次插入元素都会使树重新调整,将所有元素排序后以缩进列表方式展示。具有重载优化特性,每一次插入只需要更改相关节点指向,速度稳定。

性能:

  • HashMap

    • insert:平均为 O(1),最坏情况可能退化成 O(n);
    • delete:平均为 O(1),最坏情况可能退化成 O(n);
    • search/get:平均为 O(1),最坏情况可能退化成 O(n)。
  • TreeMap

    • insert:每次将节点插入到红黑树中,时间复杂度平均为 O(logN);
    • delete:删除节点后调整节点替代者连接以保持树的性质,时间复杂度平均为 O(logN);
    • search/get:二分查找,时间复杂度平均为 O(logN)。

        从时间复杂度角度看,HashMap 插入、删除和随机访问元素都具有常数复杂度 O(1),但并不保证最坏情况下的稳定性;而 TreeMap 的插入、查询和删除操作的时间复杂度都为 O(logN),稳定性更好,但在数据量较大时表现可能会相对较差。此外,HashMap 在考虑键值映射唯一性时需要考虑键值的 HashCode 计算和哈希函数冲突问题,而 TreeMap 没有这个问题。


 等价比较:

    HashMap 判断两个键是否“相等”的标准是 hashCode() equals() 方法,而 TreeMap 判断两个键是否“相等”的标准是 comparator()compareTo() 方法。所以TreeMap的等价比较会更加的灵活点


线程安全:

    HashMapTreeMap 都是非线程安全的集合,即它们不支持多线程并发访问。如果在无并发保护的情况下同时进行多个写操作,则可能导致数据丢失、数据结构损坏等问题。

使用适当的同步工具

  • HashMap 可以使用 Collections.synchronizedMap() 方法或者 ConcurrentHashMap 类来提供线程安全的访问方式。其中 synchronizedMap() 方法返回一个同步的 Map 包装器,在需要同步时将方法调用委托给原始 Map,从而确保线程安全。
  • TreeMap 不提供直接的实现来获得线程安全,因此可以考虑通过读写锁 ReentrantReadWriteLock 或其他同步工具来确保并发访问的安全。

 避免在多线程环境下直接修改集合

        另外一种方法是避免在多线程环境下修改导致并发问题的集合(例如添加/删除元素)。在多线程访问时,可以使用 CopyOnWriteArrayList 等类,即对原有数据进行快照形成新的数组,由于通常在快照 (也就是对象内部存储的数组) 上执行写操作,所以所有副本可以自由地读取。

在多线程读取或遍历时避免遍历未同步的集合。对于高度竞争的数据访问,可以考虑其它采用单例、缓存或异步等方式来保证安全性。


选型建议:

        对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。

  • 对于少量数据元素的存储,使用 TreeMap 合适(O(NlogN) 的常数较小)。
  • 对于元素数量相对更多的场景,可以使用 hash 实现的 HashMap(O(1) 的时间复杂度)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学徒630

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值