Hashtable.keySet()的顺序?

问题描述 投票:0回答:2

最近在学习Java,有一个问题。

我了解到

HashMap
Hashtable
不保留插入顺序或基于键的顺序。但我遇到过不遵循的情况

import java.util.HashMap;
import java.util.Hashtable;

public class Main {
    public static void main(String[] args) {

        Hashtable<Integer, Integer> hashtableInt = new Hashtable<>();
        Hashtable<String, Integer> hashtableStr = new Hashtable<>();
        HashMap<Integer, Integer> hashMapInt = new HashMap<>();
        HashMap<String, Integer> hashMapStr = new HashMap<>();

        for (int i = 0; i < 25; i++) {
            hashtableInt.put(i, i);
            hashtableStr.put(String.valueOf(i), i);
            hashMapInt.put(i, i);
            hashMapStr.put(String.valueOf(i), i);
        }

        System.out.println("Hashtable with Integer keys : ");
        for (int key : hashtableInt.keySet())   System.out.print(key + " ");

        System.out.println("\n\nHashtable with String keys : ");
        for (String key : hashtableStr.keySet())   System.out.print(key + " ");

        System.out.println("\n\nHashMap with Integer keys : ");
        for (int key : hashMapInt.keySet())   System.out.print(key + " ");

        System.out.println("\n\nHashMap with String keys : ");
        for (String key : hashMapStr.keySet())   System.out.print(key + " ");
    }
}
Hashtable with Integer keys : 
24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 

Hashtable with String keys : 
19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 24 3 23 2 22 1 21 0 20 

HashMap with Integer keys : 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 

HashMap with String keys : 
22 23 24 10 11 12 13 14 15 16 17 18 19 0 1 2 3 4 5 6 7 8 9 20 21 %                                     

在上面的输出中,使用

Integer
键的哈希具有特定的顺序。只有采用
String
作为键的哈希值是没有顺序的。此外,
Hashtable
HashMap
之间的按键顺序与
Integer
键不同。

所以我想知道的是...

  1. 为什么

    Hashtable().keySet()
    HashMap().keySet()
    有订单?一般来说,哈希和集合没有特定的顺序。这是为什么?我错过了什么吗?

  2. 为什么

    Hashtable().keySet()
    HashMap().keySet()
    的顺序相反?毕竟,这两个都是哈希值,但是内部工作原理是否有所不同?

  3. 如果

    keySet()
    预计有订单,为什么
    Hashtable().keySet()
    HashMap().keySet()
    有不规则订单?

谢谢大家。

我已经调试了

put()
方法并观察了它是如何工作的,但这对我来说太难了。

java methods hashmap hashtable internals
2个回答
0
投票

Hashtable
HashMap
都是Java集合框架的一部分,实现了
Map
接口以通过哈希表存储键值对。
Hashtable().keySet()
HashMap().keySet()
中看到的“顺序”并不是故意的;它是密钥散列和内部数组处理的产物,无法保证随时间的一致性。对于整数键,由于 Java 的哈希函数特性(由于 Java 的
Integer.hashCode()
方法直接返回整数,键本身被重用为哈希码)以及哈希表如何管理冲突和调整大小,因此该顺序看起来有些可预测。然而,对于字符串键,哈希函数的复杂性会导致顺序难以预测。

Hashtable
HashMap
之间的顺序差异源于它们不同的实现。
Hashtable
更旧,同步,并且通常更慢,显示出更稳定的迭代顺序。
HashMap
随着时间的推移进行了优化,影响了其迭代顺序的不可预测性。

关键要点是,在这些集合中观察到的顺序是偶然的,受到 Java 哈希机制和集合内部结构的影响。对于有保证的订单,您应该使用

LinkedHashMap
来表示插入顺序,或者如果您想要排序顺序,则应使用
TreeMap


0
投票

您不能依赖订单。虽然这种情况的发生并不是真正的“随机”,但人们绝对可以认为这是偶然的。

这是因为哈希数据结构存储数据的方式。这些依赖于将数据分布在多个存储桶上(通常存储桶的数量多于数据点的数量)。 为了决定哪个数据点进入哪个桶,它调用对象的

hashCode
方法,然后使用模数运算将其分配到桶中。在
Integer
的情况下,这 恰好会返回原始号码

因此,如果您有 10 个桶并将数字 1,2,3,4,5,5,6 存储在这些桶中,则数字 1 将进入桶 1,而 2 将进入桶 2,依此类推。如果数字分布得更分散,这将不再有效。

© www.soinside.com 2019 - 2024. All rights reserved.