HashMap的key为Integer时为什么有序

首先我们知道,HashMap遍历的顺序和插入的顺序是不一样的,而LinkedHashMap遍历的顺序和插入的顺序是一致的。看代码

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class Main{
    public static void main(String[] args) {
        Map<String, Integer> map2 = new HashMap<>();
        map2.put("Abc", 1);
        map2.put("css", 2);
        map2.put("Zxe", 3);
        LinkedHashMap<String, Integer> linkedHashMap2 = new LinkedHashMap<>();
        linkedHashMap2.put("Abc", 1);
        linkedHashMap2.put("css", 2);
        linkedHashMap2.put("Zxe", 3);

        for (Map.Entry entry : map2.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
        for (Map.Entry entry : linkedHashMap2.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
    }
}

打印结果如下:

css:2
Abc:1
Zxe:3
Abc:1
css:2
Zxe:3

很明显,使用LInkedHashMap遍历是有序的,而使用HashMap是无序的。

但是另外一种情况,当key为Integer时,就不一样了。

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class Main{
    public static void main(String[] args) {
        Map<Integer, Integer> map1 = new HashMap<>();
        LinkedHashMap<Integer, Integer> linkedHashMap = new LinkedHashMap<>();
        for (int i = 0; i < 5; i++){
            map1.put(i, i * 2);
            linkedHashMap.put(i, i * 2);
        }
        for (Map.Entry entry : map1.entrySet()){
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
        for (Map.Entry entry : linkedHashMap.entrySet()){
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
    }
}

打印结果如下:

0:0
1:2
2:4
3:6
4:8
0:0
1:2
2:4
3:6
4:8

当key为Integer传入HashMap时,它的遍历结果仍然是有序的。

原因剖析

先来看HashMap的get()方法,get()方法会传入一个key,然后计算它的hash值。

hash值计算:如果key为null就返回0;如果不是null,那么就先计算key的hashCode值,并将它右移16位和原来的hashCode值进行异或得到这个key的hash值。

    public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

继续看hash方法

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

猜想:之所以传入Integer时会有序,是不是因为Integer的HashCode值比较特别?

来看Integer中的hashCode代码,发现Integer对象中的hashCode方法,返回的就是当前value,所以插入的时候有序,遍历的时候也是有序的。

    @Override
    public int hashCode() {
        return Integer.hashCode(value);
    }


    // 问题所在
    public static int hashCode(int value) {
        return value;
    }

结论

        当key为Integer对象时,HashMap之所以是有序的,就是因为Integer计算出来的hashCode值是有序的,因为Integer对象重写的hashCode方法中,就是直接返回的value值。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值