zoukankan      html  css  js  c++  java
  • 当Hashtable和HashMap添加自身时

    今天在看Hashtable的toString()源码时,看到了其中有一个"key == this"的判断,于是突发奇想,如果用Hashtable添加自身再做一些别的操作会怎样?

    ①,hashCode方法

    先看代码:

    1     public static void main(String[] args) {
    2         Hashtable table = new Hashtable();
    3         table.put(table, 1);
    4         System.out.println(table.hashCode());
    5 
    9     }

    如果我们运行这段代码,好,正常运行,输出1。

    接下来再用HashMap试一下同样的代码:

    1     public static void main(String[] args) {
    2         HashMap map = new HashMap();
    3         map.put(map, map);
    4         System.out.println(map.hashCode());
    5     }

    运行,结果:

    竟然出StackOverFlowException异常了!这是为什么呢?

    来分别看看他们的代码:

    Hashcode的源代码如下:

     1 public synchronized int hashCode() {
     2         /*
     3          * This code detects the recursion caused by computing the hash code
     4          * of a self-referential hash table and prevents the stack overflow
     5          * that would otherwise result.  This allows certain 1.1-era
     6          * applets with self-referential hash tables to work.  This code
     7          * abuses the loadFactor field to do double-duty as a hashCode
     8          * in progress flag, so as not to worsen the space performance.
     9          * A negative load factor indicates that hash code computation is
    10          * in progress.
    11          */
    12         int h = 0;
    13         if (count == 0 || loadFactor < 0)
    14             return h;  // Returns zero
    15 
    16         loadFactor = -loadFactor;  // Mark hashCode computation in progress
    17         Entry[] tab = table;
    18         for (int i = 0; i < tab.length; i++)
    19             for (Entry e = tab[i]; e != null; e = e.next)
    20                 h += e.key.hashCode() ^ e.value.hashCode();
    21         loadFactor = -loadFactor;  // Mark hashCode computation complete
    22 
    23     return h;
    24     }

    看了代码是不是一目了然了呢。代码里面有一个guard来阻止了死循环。

    就是loadFactor = -loadFactor;就是说代码调用key(就是hashtable自身)的hashCode时,此时loadFactor已经成了负值,那么就直接返回0了,所以不会一直死循环下去。

    而HashMap却没有这个guard来阻止死循环,所以就崩掉了。

    ②,remove方法

    先上代码:

    1     public static void main(String[] args) {
    2         Hashtable table = new Hashtable();
    3         table.put(table, 1);
    4         System.out.println(table);
    5         table.remove(table);
    6         System.out.println(table);
    7     }

    运行结果如下:

    {(this Map)=1}
    {(this Map)=1}

    很明显,remove方法没有把里面的table删掉,why?

    其实,remove方法执行时,要找到这个table在内部数组中的位置,查找的依据就是key的hashCode,代码如下:

    for (int i = 0; i < tab.length; i++)
                for (Entry e = tab[i]; e != null; e = e.next)
                    h += e.key.hashCode() ^ e.value.hashCode();

    因为table已经发生了变化,所以其hashCode值也发生了变化,跟之前插进去的时候的值已经不一样了,所以就删除不掉了。

  • 相关阅读:
    Atom编辑器快捷键大全
    sql随机
    InnoDB表要建议用自增列做主键
    Nginx优化
    Nginx访问限速配置方法详解
    checking for known struct flock definition... configure: error: Don't know how to define struct flock on this system, set --enable-opcache=
    阿里巴巴技术质量新人手册4-研发过程中的测试工作
    阿里巴巴技术质量新人手册3-如何做到测试场景不遗漏
    阿里巴巴技术质量新人手册2-修炼测试基本功
    阿里巴巴技术质量新人手册1-测试开发工程师的角色
  • 原文地址:https://www.cnblogs.com/huashui/p/3213949.html
Copyright © 2011-2022 走看看