HashMap散列表

HashMap散列表

数据结构

HashMap是由动态链表和红黑树的结构组成,而组成这些结构的是一个个桶结构;当map中链表长度小于64并且深度小于6的时候map将保持动态链表的结构,当不满足就会转化为红黑树的结构。

散列表处理冲突的方法

  1. 开放地址法:如果根据key计算出的hash出现了冲突,则去寻找下一个空的桶位置去存放。

    • 优缺点

      • 优点:简单,表不满的时候性能好
      • 缺点:邻插槽会形成“集群”,当这些簇填满阵列的时候性能会严重下降,因为是穷举搜索
    • 线性探测法

    • 二次探测法

      • 可以将原本冲突时存放hash+1改为hash*hash,也就是平方探测法,这样可以防止聚集(可是这种方法对于后面插入的元素,探测时间会延长,也就是所谓“二次聚集”)
    • 随机探测法

  2. 再散列函数法:二次hash,需要寻找合适的函数

  3. 链地址法:这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。

    • 优点:简单
    • 缺点:当链表中存放大量元素的时候,查询效率下降,所以需要对数组进行扩容。
  4. 建立一个公共溢出区

线程安全的map

  1. Hashtable线程安全,但效率低,因为是Hashtable是使用synchronized的,所有线程竞争同一把锁;
  2. ConcurrentHashMap不仅线程安全而且效率高,因为它包含一个segment数组,将数据分段存储,给每一段数据配一把锁,也就是所谓的锁分段技术。

equals和hashCode

  • equals是Object类的方法:主要是比较地址值
    1. 对于String字符串来说equals是比较字符串中的内容是否相同,而“==”是比较两个对象在内存中的地址值。另外StringBuffer中没有重新定义equals方法,所以它是来自Object类的。
  • hashCode是用来计算对象在内存中的hashCode值
    1. 存对象到集合中是怎么判断一个对象是否已经在集合中呢?首先会用计算hashCode如果hashCode发生冲突了,则判断集中已经有这个对象(内存相同),如果hashCode没有相同,则再用equals判断是否是同一个对象,如果不是,才会添加到集合中。
    2. 也就是说两个对象,hashCode相同,那么他们指向的地址一定相同,并且equals也相同;如果hashCode不相同,也不能说明他们就是不同对象,要根据equals判断。
    3. 需要注意的是当equals()方法被override时,hashCode()也要被override。按照一般hashCode()方法的实现来说,相等的对象,它们的hash code一定相等。

HashMap

Hash是什么

  • 通过对象的内部地址(也就是物理地址)转换成一个整数,然后该整数通过hash函数的算法就得到了hashcode,所以,hashcode是什么呢?就是在hash表中对应的位置。

Hash的计算

  • 为什么右移 16 位,为什么要使用 ^ 位异或

  • HashMap 如何根据 hash 值找到数组中的对象

    final Node<K,V> getNode(int hash, Object key) {
         
        Node<K, V>[] tab; Node<K, V> first, e; int n; K k;
        if((tab = table) != null && (n = tab.length) > 0 && 
          // 需要关注下面这一行
          (first = tab[(n - 1) & hash]) != null) {
         
            if( first.hash == hash && // always check first node
              ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
            
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值