对 HashMap<Integer, String>调用 get(byte 变量) 为何取不到值? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
amiwrong123
V2EX    Java

对 HashMap<Integer, String>调用 get(byte 变量) 为何取不到值?

  •  
  •   amiwrong123 2020-03-30 13:46:11 +08:00 5101 次点击
    这是一个创建于 2026 天前的主题,其中的信息可能已经有所发展或是发生改变。
    public class test { public static void main(String[] args) throws IOException{ HashMap<Integer, String> map= new HashMap<>(); map.put(1,"one"); String aa = map.get(1); byte b =1; String bb = map.get(b); } } 

    如上代码,为何 bb 变量是 null 呢,感觉不是 byte 自动转型为 int,再自动装箱为 Integer 吗

    24 条回复    2020-03-31 19:47:42 +08:00
    IMCA1024
        1
    IMCA1024  
       2020-03-30 13:52:14 +08:00
    .....Integer 做 key 啊。
    为什么推荐用 String 做 key 呢?

    原理我不太会说,但我觉得问题在 你这个 byte b=1 的 hash 值 并不能拿到 key 为 Integer=1 的。。
    希望楼下的能给我说明一下 哈哈哈
    mm163
        2
    mm163  
       2020-03-30 13:54:30 +08:00
    HashMap<Integer, String> map= new HashMap<Integer, String>();
    EPr2hh6LADQWqRVH
        3
    EPr2hh6LADQWqRVH  
       2020-03-30 13:57:30 +08:00 via Android   1
    要射自己脚的话直接 c++就完了嘛
    earther01
        4
    earther01  
       2020-03-30 14:01:11 +08:00
    看了下 get 前强转一下就行了,不转的话应该是认为传进去的是 object 的地址,会先寻址找到地址对应的 object
    airfling
        5
    airfling  
       2020-03-30 14:03:21 +08:00
    我刚刚测试了下你没加强转的话是取 byte 的 hash 值取值的,加了强转的话就是一样的值了
    下面是 map 中的 get
    ~~~
    public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
    }
    ~~~
    map.get((int)b) 这样获取的值就是一样的
    h3nng
        6
    h3nng  
       2020-03-30 14:15:26 +08:00
    补充下楼上说的,hash 值其实是一样的,都是 1,但是 == 或 equals() 为 false
    amiwrong123
        7
    amiwrong123  
    OP
       2020-03-30 14:29:45 +08:00
    @airfling
    好吧,大概懂了。我主要之前以为函数签名是泛型类型呢 public V get(K key) {
    p2pCoder
        8
    p2pCoder  
       2020-03-30 14:33:29 +08:00
    只会触发装箱,没有触发转型
    lux182
        9
    lux182  
       2020-03-30 14:59:32 +08:00
    个人猜测:byte 封装为 Byte 。Byte _b = 1 与 Integer _a = 1 的 hash 、equals 应该有不同
    ChenFanlin
        10
    ChenFanlin  
       2020-03-30 15:23:28 +08:00
    yeqizhang
        11
    yeqizhang  
       2020-03-30 16:29:12 +08:00 via Android
    @mm163 不是应该这么写?:HashMap map= new HashMap<Integer, String>();
    guyeu
        12
    guyeu  
       2020-03-30 16:31:16 +08:00
    因为 HashMap.get(Object)接受任意类型的参数,当传入基本数据类型时,会触发自动装箱。

    如果你声明一个这样的方法,用来替换 HashMap.get ,就会先触发类型转换,然后触发自动装箱;

    ```java
    static <T> T get(HashMap<?, T> map, int key) {
    return map.get(key);
    }
    ```

    java 貌似不支持同一个位置既自动类型转换又自动装箱。。
    elevation
        13
    elevation  
       2020-03-30 16:35:15 +08:00
    如果想彻底了解,需要学习 HashMap 源码中 put 运行机制;还有你需要写明白,自己的开发环境
    yeqizhang
        14
    yeqizhang  
       2020-03-30 16:36:30 +08:00 via Android
    @mm163 我搞错了,楼主的是没问题的。菱形泛型
    amiwrong123
        15
    amiwrong123  
    OP
       2020-03-30 16:55:34 +08:00
    @guyeu
    java 不支持同一个位置既自动类型转换又自动装箱么,回头我试下

    对,自己再写个方法可以哈。话说,你那个泛型方法 应该这样吧:

    ```java
    static <K,V> V get(HashMap<K, V> map, K key) {
    return map.get(key);
    }
    ```
    yjxjn
        16
    yjxjn  
       2020-03-30 18:17:59 +08:00
    @mm163 楼主这个没写错呀,后面的菱形里面不声明也可以、
    cco
        17
    cco  
       2020-03-30 18:55:36 +08:00
    @yeqizhang HashMap<String, Object> map= new HashMap<>();
    guyeu
        18
    guyeu  
       2020-03-30 22:17:59 +08:00
    @amiwrong123 #15 你这样写没办法出发自动类型转换(你这个只不过是把 HashMap 自带的 get 方法换了个写法)
    dreamist
        19
    dreamist  
       2020-03-30 23:17:36 +08:00
    这个代码,在 Kotlin 里面是会编译报错的,所以,Kotlin 欢迎你~~ hhh
    dreamist
        20
    dreamist  
       2020-03-30 23:20:40 +08:00
    这个问题,究其原因,还是 HashMap 的锅,HashMap 的 get 方法参数是没有泛型约束的:
    public V get(Object key) {
    }

    所以在 get 的时候,传入的类型,是允许和 HashMap 定义时的 key 类型是不一致的,这就导致了这样的问题无法在编译期间暴露出来。
    1194129822
        21
    1194129822  
       2020-03-30 23:45:42 +08:00 via Android   1
    楼主对 hashmap,基本类型及其包装类,自动装箱及隐私类型转换,类型提升不是很熟悉啊。首先 Java 泛型并不支持基本类型,java 默认的整型是 int,浮点数是 double,所以没有特别标注 1,2 这些字面量表示就是 int,当在泛型方法中使用时,会自动装箱为 Integer,如果强行指定(byte)1 则会包装为 Byte,hashmap 判定两个元素是否相等是 equals,而 hashcode 相同只是处在相同的 bin 中。所以当然为 null 啦,而 Integer(1)与 Byte(1)当然就不相同啦,这里还有个坑,因为 Byte,Integer 缓存了 1byte 的值,所以你 put/get(1)多少次只是 1 个包装对象,而 get(128)就会每次生成一个新对象,虽然包装类都重写了 equals,但还是会稍微影响点性能,而 java 默认的隐式类型装是针对基本类型的,换是 int 可以接受 byte,注意 Byte 不能转换为 Integer 。而类型提升也是针对基本类型的,算数位移等运算符只能是基本类型,并且默认提升到***int***,所以 byte(1)+byte(1)=int(2). 所以你只要 get(byte(1)+0)就相当于 get(1)了,推荐看一下 java 规范
    xiaowangge
        22
    xiaowangge  
       2020-03-31 00:42:50 +08:00   1
    1 、debug 大法好:
    在 IDEA 中,在 `String bb = map.get(b);` 这一行打断点,然后 debug 运行,force step into

    public static Byte valueOf(byte b) {
    final int offset = 128;
    return ByteCache.cache[(int)b + offset];
    }



    2 、javap 大法好:

    35: invokestatic #9 // Method java/lang/Byte.valueOf:(B)Ljava/lang/Byte;
    Aresxue
        23
    Aresxue  
       2020-03-31 15:21:18 +08:00
    很有趣的问题, 看了下源码 byte b 在处理时被装箱成了 Byte,有趣的是 new Byte(1)和 new Integer(1)的 hashCode 是一样的, 这很容易让人困惑, 但在 HashMap 569 行(k = first.key) == key || (key != null && key.equals(k))) 中对 key 除了 hashCode 的判断还有对类型的判断(见 Integer equals 方法 974 行)。同理你使用 map.get(new Integer(1)) 就可以取出对应的值来, 哪怕不是同一个对象也依旧可以取出你想要的值, 因为 new Integer(1) equals new Integer(1)
    SoloCompany
        24
    SoloCompany  
       2020-03-31 19:47:42 +08:00
    关键在于 Map.get 的签名是 get(Object key) 而并不是 get(K key)

    虽然 put 的签名是 put(K key, V value)

    然而 get 和 put 并不对等
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5399 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 08:14 PVG 16:14 LAX 01:14 JFK 04:14
    Do have faith in what you're doing.
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-11940834-2', 'v2ex.com'); ga('send', 'pageview'); ga('send', 'event', 'Node', 'topic', 'java'); ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86