【问题标题】:HashMap order of insertion [duplicate]HashMap的插入顺序[重复]
【发布时间】:2016-06-05 21:03:42
【问题描述】:

知道HashMap以无序方式存储和检索元素时,为什么HashMap以有序方式检索

HashMap m = new HashMap();
m.put("A", 1);
m.put("B", 2);
m.put("C", 3);
m.put("D", 4);
m.put("E", 5);

Set keySet = m.keySet();
Iterator it = keySet.iterator();
while(it.hasNext())
{
    System.out.println(m.get(it.next()));
}

输出 - 1 2 3 4 5

【问题讨论】:

  • “当知道 HashMap 以无序的方式存储和检索元素时” 明确一点:这并不意味着 HashMap 会混淆你的元素只是为了无序。这只是意味着您不能依赖任何订单。您仍然可以得到和“有序”的输出。

标签: java collections hashmap


【解决方案1】:

恰好在这种特殊情况下,A B C D E 的hashCodes 的排序越来越多。

 while(it.hasNext())
 {
    String next = it.next();
    System.out.println(next.hashCode() + " "+ m.get(next));
 }

会产生如下

65 1
66 2
67 3
68 4
69 5

但是,这并不意味着每次您拥有一组越来越有序的哈希码时,映射条目都将按其哈希码的顺序存储。

【讨论】:

  • 仅仅因为哈希是有序的并不意味着它们在实际的HashMap 中是有序的。在实际用作索引之前,哈希码还有一些混乱。
  • 当然,mod 哈希和哈希表大小起了作用,不过我不知道该怎么说 :(
  • 这就是我没有尝试的原因。混乱可以采取任何形式,并且 确实 在不同的 Java 实现之间有所不同;这些元素的顺序在不同的 Java 版本中会有所不同。这就是为什么我故意将这些元素按正确顺序放置的原因保持开放式:因为从来没有任何保证它们会保持正确的顺序。
  • 看起来stackoverflow.com/a/2144822/869736 实际上有一个非常棒的答案。我倾向于将其标记为重复,只是因为该答案非常好。
【解决方案2】:

简而言之:你很幸运。HashMap 通常以任意无意义的顺序返回元素,而这种情况恰好是所有元素都按顺序出现的情况。

【讨论】:

  • 但是每次我运行这个。它给了我相同的顺序
  • HashMap 的实现依赖于键的 hashCode,对于字符串,每次运行的 hashCode 都是相同的。尝试更改您的密钥,看看会发生什么。
  • @ArijitDasgupta 这不是随机的,只是没有指定。实施不做任何保证。幸运的不是跑步,幸运的是您选择的钥匙。
【解决方案3】:

因为两件事:

这是hashCode()String的实现:

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

对于一个字符的字符串,它只是该字符的 Unicode 值。这些字母 (A-E) 具有连续的值 (65-69)。

HashMap class modifies the hash a little bit,但在这种低值的情况下,值不受影响。

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

HashMap will reduce the hash code modulo the number of buckets 查找密钥的桶号。在这种情况下,桶号都是连续的——12345。所以,迭代器按顺序遍历桶。

如果发生任何这些事情,其中​​一些不在HashMap 合同中并且不在您的控制范围内,那么迭代顺序可能会改变。

  • 添加其他不具有相同商模 16 的键,例如“Z”、“a”、“AA”。
  • 创建默认容量较小的地图。
  • Java 决定弄乱HashMap 内部的hash 方法。
  • Java 决定弄乱将哈希码映射到 HashMap 内部的存储桶编号的算法。
  • Java 决定弄乱String 中的hashCode 方法。

【讨论】:

    猜你喜欢
    • 2021-02-24
    • 2022-01-21
    • 2013-10-10
    • 1970-01-01
    • 2020-11-28
    • 2011-01-09
    • 2013-05-27
    • 1970-01-01
    相关资源
    最近更新 更多