zoukankan      html  css  js  c++  java
  • HashMap学习笔记

     

     

    概述

     

    HashMap是Map接口的一个哈希表的实现,内部是一个数组表示的。数组中的元素叫做一个Node,一个Node可以一个是一个简单的表示键值对的二元组,也可以是一个复杂的TreeNode。如果是一个一个简单的二元组,则可以通过Node的next域构成构成一个链表。

      transient Node<K,V>[] table;
        
    
     

    当需要遍历Map的时候,建议使用entrySet域来进行遍历,而不是keySet。因为entrySet其实返回的是一个特殊的set,这个set并未保存任何元素,而是定义了一个特殊的迭代器,这个迭代器直接遍历map中的table,因此能直接得到一个entry的键和值,也就是说,使用entrySet进行遍历的时候,一次遍历即可。(hash冲突除外)。而使用keyset得到的只是key的set,使用key去获取value的时候,还需要进行一次查找。

     

    如果只需要值,那么就调用values方法,此方法返回一个特殊的集合,它保存了一个entryset,并使用entryset的迭代器对table进行访问,因此效率也是很高的。

     

    方法详述

    • comparableClassFor
      Class<?> comparableClassFor(Object x)
      获取对象x的可比较的class,即尝试从对象x中找到一个Comparable<x.getClass()> 对象。
      首先检查对象x是否是一个comparable的实例:
      if (x instanceof Comparable)
      如果是的话,获取x的class,顺便检查一下是否是String,因为Stirng是用的最多的,顺便加个速。
      如果不是String类,那么就获取此类直接实现的接口(注意,一定是直接实现的)。
      c.getGenericInterfaces())
      然后判断每个父接口是否是参数化类型,且参数化类型的具体类型为compare:
      if (((t = ts[i]) instanceof ParameterizedType) &&
      ((p = (ParameterizedType)t).getRawType() ==
      Comparable.class)
      如果是的话,取出此参数化类型的实际参数类型,如果确实存在,且参数类型和对象x的类型相同,那么这个父接口就是最终要找的comparable接口了。
      (as = p.getActualTypeArguments()) != null &&
      as.length == 1 && as[0] == c) //

    • tableSizeFor

            int tableSizeFor(int cap) int n = cap - 1; n |= n >>> 1; n |= n
              >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>>
              16; return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY
              : n + 1;
              
          

      这段代码非常巧妙,通过位移和或运算计算出比cap大的最小的2的N次方的值。
      第一行:cap-1是为了解决cap本来就是2的N次方的问题。
      然后进行一次右移,一次右移的效果是:如果某一为本来是1,那么一次位移并或之后,它的低一位也会变成1.这样就将一个1变为2个1了。如果本来是0,那么还是0.
      第一步已经将一个1变为2个1了,那么第二步右移两位,就能将两个1变为4个1,接着变为8个1,16个1,最多不超过32个1.
      这个数字最终的效果是,从低往高看,后面的位数上全是1,然后这个数加1,就是原始的cap的2的N次方最小值了。

    • putVal
      第一步:找到带加入的key所在的桶,使用的办法是用桶数组的大小减1然后和hey的哈希值进行与,这其实是让key的哈希值对桶的大小取余的简便操作,提升了效率。
      第二步:如果桶中当前没有元素,则加入,完成。如果桶中已经有值了,说明发生了hash冲突,此时需要将新加入的值沿着桶中已有的值往下排,构成一个链表。
      在第二中,如果一个桶中的元素超过了一个阀值,默认为8,则不再使用链表来保存桶中的元素,而是改成用二叉查找树来保存,以提高检索效率。
      如果桶中的元素当前已经是一个二叉查找树了,那么就加新元素加入到树中。

      加入一个新元素之后,需要检查Map的数量是否满足填装因子的限制,如果不满足了,需要进行重新hash。

  • 相关阅读:
    多模块应用自动化部署
    shell杀死指定端口的进程
    SpringBoot打包成war
    Spring Boot:The field file exceeds its maximum permitted size of 1048576 bytes
    nginx上配置phpmyadmin
    Ubuntu16.04中php如何切换版本
    E:dpkg was interrupted, you must manually run'dpkg配置'to correct the problem.
    Edusoho之LAMP环境搭建
    cocos2d-x -3.81+win7+vs2013开发环境创建新的项目
    M2Mqtt is a MQTT client available for all .Net platform
  • 原文地址:https://www.cnblogs.com/humc/p/5385126.html
Copyright © 2011-2022 走看看