for (int i = oldCapacity ; i-- > 0 ;) {
            for (Entry old = oldMap[i] ; old != null ; ) {
                Entry e = old;
                old = old.next;
 
                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                e.next = newMap[index];
                newMap[index] = e;
            }
        }
这段看不懂,求大神解释下
old.hash和old.next.hash一样吗
不一样的话每条链表的的一个节点就会占用newMap[]的一个容量是吗,不是一整条链存占数组的一个容量吗?

解决方案 »

  1.   


    我觉得你先弄清一个链式节点的结构是啥,再反过来看程序。我不知道为什么每次循环e.hash都是一样的,能分析一下吗
      

  2.   

    怎么可能一样的;
    Entry e=old;//当前的给e
    old=old.next;//old指向下个链接
    这里不是每次重新都赋予过了么!
      

  3.   

    e.hash每次都不一样那每次的index就不一样,那是不是就是把oldMap[i]的链表的每个节点都独占一个newMap[index]?
      

  4.   

    e.hash每次都不一样那每次的index就不一样,那是不是就是把oldMap[i]这个链表的每个节点都独占一个newMap[index]?不是一条链表存储一个newMap[index]吗?这个循环不是把oldMap[i]这条链表转到newMap[index]吗?
      

  5.   


    没错,把oldMap旧数据的内容传入新数据newMap中 
      

  6.   

    hashtable 是根据key生成一个hash,然后把hash通过  int index = (hash & 0x7FFFFFFF) % Capacity;取得数据下标,然后存入数组下标的链表内,所以一个数组节点对应一个链表,下标内有几对值完全都是随机的。
     
      

  7.   

    关键是%capacity 这是代表根据数组的长度取模,所以不管hash值是多少, (hash & 0x7FFFFFFF) 先保证hash的符号,然后取模落在数组的长度内。虽然把旧表的数据全部拷贝到新表,但是拷贝位置是不一样的,会被重新排列,所以hashtable是散列的,无序的。
      

  8.   

    这层循环每次的index相不相同?
    如果获取的oldMap[i]是一条有三个节点的链表,那这个循环是不是就循环三次,每次获取oldMap[i]的一个节点放到newMap[index].next直到最后null就退出这层循环?
    如果每次的index不一样那不就是相当于把oldMap[i]的三个节点分别存到三个不一样的newMap[index]吗?这样rehash后原先的链表结构不就变了?
      

  9.   


    你先要明白你看的代码是啥,这个应该hashtable的扩容中代码,都说了hashtable是散列结构,你先搞明白什么是散列结构。扩容后存放位置会根据int index = (hash & 0x7FFFFFFF) % Capacity;改变。
      

  10.   

    我说的是第二层循环,第二个for,第二个for!
    我知道扩容后位置会改变!但那只是链表的在数组里的位置变了,链表里的节点不会被拆到别的地方吧?
      

  11.   

    具体保存在哪个下标链表中是根据新的数组长度与hash值取模获取的。你自己推导一下不就明白了么 ,15用8取模是7 ,扩容后15用16取模是15; 同样 7用8取模是7 ,7用16取模是7 肯定被打散了。
      

  12.   

    比如oldMap[i]扩容前是有一条有两个key都一样value不一样的节点的链按你那么说是不是扩容后会把这条链的两个节点拆出来分别存储在newMap[index1]和newMap[index2]
    那样不就会Key不就会重复了?
      

  13.   


    我不明白你key不会重复的意思,hashcode本身就不存在重复性,key本身就是唯一,hashtable本身就不存在重复的key。都说了hashtable本身的存放是一个数组,而每个数组节点就是一条链表,本身存放就是散乱的,有的数组节点可能存放了好几个键和值,有的数组节点可能一对键和值都没有。放入新数组的下标是也是根据hashcode取模决定,这时候取模的值是新数组的长度,这条链的两个节点拆出来,可能会有2个新数据下标情况,也可能2个都在一个新下标中情况,也可能新数组下标和原来的下标一样的情况。
      

  14.   


    我不明白你key不会重复的意思,hashcode本身就不存在重复性,key本身就是唯一,hashtable本身就不存在重复的key。都说了hashtable本身的存放是一个数组,而每个数组节点就是一条链表,本身存放就是散乱的,有的数组节点可能存放了好几个键和值,有的数组节点可能一对键和值都没有。放入新数组的下标是也是根据hashcode取模决定,这时候取模的值是新数组的长度,这条链的两个节点拆出来,可能会有2个新数据下标情况,也可能2个都在一个新下标中情况,也可能新数组下标和原来的下标一样的情况。
    你确定hashCode不存在重复?
      

  15.   

    hashtable 链表一个节点的结构Entry<K,V>{
    哈值
    int hash;
    K key;
    V value;
    // 指向的下一个Entry,即链表的下一个节点
    Entry<K,V> next;
    }
      

  16.   


    2个hashcode一样,代表这2对key和value完全相同,hashtable存在 这样的2对键值么?
      

  17.   

    我上面有点说错这里hash指的是key的hash,你先要了解hashtable是什么类型的列表。hashtable中不存在重复的key,如果key相同在put源代码中有判断,key相同时直接替换value值,下面是put源代码。public synchronized V put(K key, V value) {
    // Hashtable中不能插入value为null的元素!!!
    if (value == null) {
    throw new NullPointerException();
    } // 若“Hashtable中已存在键为key的键值对”,
    // 则用“新的value”替换“旧的value”
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry<K, V> e = tab[index]; e != null; e = e.next) {
    if ((e.hash == hash) && e.key.equals(key)) {
    V old = e.value;
    e.value = value;
    return old;
    }
    }
    }
      

  18.   


    2个hashcode一样,代表这2对key和value完全相同,hashtable存在 这样的2对键值么?
    链表是用来解决hashcode重复的,两个hashcode一样的会形成链表,然后首节点还是方在相对应的数组下标下面
      

  19.   

    我觉得楼主根本没搞懂hashtable 结构,hashtable的长度,不是根据数组来的,hashtable的长度是根据插入节点数来的,只要向数组的任何一个下标的链表插入一个节点,列表长度加1,数组的长度是当前列表容量的最大值。列表有自己的扩容率,当列表长度与数组比值大于扩容率的话,列表会自动扩容。
      

  20.   

    还是看图会清楚点,下面是一个8容量存放了5个对键值(实际容量为5)的hashtable列表,这只是举个例子,Hashtable默认的“加载因子”是0.75, 默认的总容量大小是11,当Hashtable的 “实际容量” >= “阈值”时,(阈值 = 总的容量 x 加载因子),就将变为“原始容量x2 + 1”。
      

  21.   

    确实hash值在这里相不相等完全没关系,一样都能存入链表中,不同的列表会有不同的判断是否要插入新节点的标准。
      

  22.   

    Hash值相等的会存入同一个数组下标的链表中,怎么就没关系了?
      

  23.   

    Hash值相等的会存入同一个数组下标的链表中,怎么就没关系了?请先理解我说的文字意思,这里存不存入链表跟hash有关系?
      

  24.   

    Hash值相等的会存入同一个数组下标的链表中,怎么就没关系了?请先理解我说的文字意思,这里存不存入链表跟hash有关系?
    Hash决定下标,如果该下标上没值,直接存进去,若有值存入还值所在的链表,你说有没有关系?
      

  25.   

    你看,这样比如扩容前数组里的一条有三个节点的链,因为是不可重复所以三个节点的key肯定都一样,如果按你的说法扩容后链的节点会被拆出来放在这个数组不同的下标里,这样数组里不就存在有相同key的链了?你自己想想先吧!
      

  26.   

    Hash值相等的会存入同一个数组下标的链表中,怎么就没关系了?请先理解我说的文字意思,这里存不存入链表跟hash有关系?
    Hash决定下标,如果该下标上没值,直接存进去,若有值存入还值所在的链表,你说有没有关系?我想知道我的理解哪里错了
      

  27.   


    我不明白你key不会重复的意思,hashcode本身就不存在重复性,key本身就是唯一,hashtable本身就不存在重复的key。都说了hashtable本身的存放是一个数组,而每个数组节点就是一条链表,本身存放就是散乱的,有的数组节点可能存放了好几个键和值,有的数组节点可能一对键和值都没有。放入新数组的下标是也是根据hashcode取模决定,这时候取模的值是新数组的长度,这条链的两个节点拆出来,可能会有2个新数据下标情况,也可能2个都在一个新下标中情况,也可能新数组下标和原来的下标一样的情况。老哥!你看清楚我说的是"不就会重复?"而不是"不会重复"!!  一个数组下标里的Key都必须是一样的
    不同数组下标里的key都必须是不一样的
    hashtable的规定就是这样
    然而你却说扩容后原来在一个数组下标里的两个节点可能会拆开存放在两个数组下标里!
    这怎么可能!这样就相当于存在不同数组下标里的key是一样的了!你认真看看!
      

  28.   

    Hash值相等的会存入同一个数组下标的链表中,怎么就没关系了?请先理解我说的文字意思,这里存不存入链表跟hash有关系?
    Hash决定下标,如果该下标上没值,直接存进去,若有值存入还值所在的链表,你说有没有关系?我只是就这段程序而言,你非要扯到全部的源代码,那我就没话好说了,源代码还有比较是否key相等呢。
      

  29.   


    兄弟我跟你这个无知的人怎么说了,你看过懂取下标的语句了么?谁跟你说下标值一样 key必定一样,取模这个感念懂不懂,我觉得你先学好基础吧,基础都没扎实看源代码,漏洞百出。
      

  30.   

    最后一次帮你解释为啥不同的key会取得相同下标,下次不再回帖了,累1个key的hash值好比是5, hashtable 数组的长度是8这时候取得的下标 5%8=5 所以取得下标是5另一个key的hash值是13这时候取得是下标 13%8=5 所以取得下标也是5所以2个会存入同一个数组下标的链中。