繁体   English   中英

从Hashtable读取值显示了自然顺序的逆

[英]Reading values from Hashtable is showing the inverse of natural order

为什么在执行以下代码时,HashMap和Hashtable在读取值时具有不同的行为,因为它们都基于用于存储值的相同哈希码方法(整数哈希码),并且这两个结构之间的唯一区别是:线程安全和允许空键和价值:

public static void main(String[] args) {
        Hashtable<Integer, String> hashtable = new Hashtable<>();
        hashtable.put(4,"4");
        hashtable.put(2,"2");
        hashtable.put(3,"3");
        hashtable.put(8,"8");
        System.out.println(hashtable.values());// [8, 4, 3, 2]

        HashMap<Integer, String> hashMap = new HashMap<>();
        hashMap.put(4,"4");
        hashMap.put(2,"2");
        hashMap.put(3,"3");
        hashMap.put(8,"8");
        System.out.println(hashMap.values());// [2, 3, 4, 8]
    }

注意:这没有记录的行为,并且在另一个JVM版本/更新或JVM实现中可能有所不同。 话虽如此,这不太可能有所不同,因为可能有程序依赖于此行为,并且没有充分的理由来更改默认实现。


对于Oracle / OpenJDK中的HashMap,它以自然顺序出现的原因是,对于较小的hashCode()值,键恰好不是随机排列在基础数组中。 对于小于负容量的非负值,该负值不会通过简单的位重新排列函数“搅乱”,hashCode的值也是数组中的索引。

HashMap的迭代器从数组的开始到结束。

在Hashtable的情况下,布局是相同的,不同之处在于values()从数组的末尾到开始迭代。

    public boolean hasMoreElements() {
        Entry<?,?> e = entry;
        int i = index;
        Entry<?,?>[] t = table;
        /* Use locals for faster loop iteration */
        while (e == null && i > 0) {
            e = t[--i];
        }
        entry = e;
        index = i;
        return e != null;
    }

我怀疑这是一个微优化,不需要将迭代器与大小进行比较,而是将其与0进行比较

简而言之,它不是线程安全的,它不允许null或初始容量。 (容量仅取决于它将适用的值的范围)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM