V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
anonymoustian
V2EX  ›  Java

Hashmap 中的 key 值为自定义类型,使用 containsKey 方法无法判断 Key 是否在 Hashmap 中,求教。

  •  
  •   anonymoustian · 2016-01-18 09:55:44 +08:00 · 5455 次点击
    这是一个创建于 3261 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在 Java 中用 Twowords 类封装了两个元素,这两个元素作为 Hashmap 的 Key 共同确定了 Hashmap 中的 Value ,但是我在写代码的过程中,需要判断 Twowords 对象是否在 Hashmap 里从而确定是否对 Value 赋值或者对 Value 进行自增操作。
    但是我写的代码并不能判断 Hashmap 是否有 Key 值,问题应该出在 new 上,请问有没有好的解决办法?

    HashMap<Twowords, Double> transitions = new HashMap<Twowords, Double>();

    Twowords tmp = new Twowords(first, second);

    if (transitions.containsKey(tmp)){
    transitions.put(tmp, transitions.get(tmp) + 1.0);
    }
    else{
    transitions.put(tmp, 1.0);
    }

    也就是说 if 判断永远为假,请问怎么解决呢? 谢谢!

    第 1 条附言  ·  2016-01-18 10:38:59 +08:00
    附加全部代码:
    public class Twowords {
    private String element1;
    private String element2;
    public Twowords(String element1, String element2){
    this.element1 = element1;
    this.element2 = element2;
    }
    public String getFirst(){
    return element1;
    }
    public String getSecond(){
    return element2;
    }
    public int hashCode(){
    return element1.hashCode()+element2.hashCode();
    }
    public boolean equals(Twowords o){
    if(o.hashCode() == this.hashCode()){
    return true;
    }
    return false;
    }
    }



    测试方法:
    public class Test {
    public static void main(String[] args) {
    Twowords tw1 = new Twowords("aa", "bb");
    Twowords tw2 = new Twowords("bb", "cc");
    Twowords tw3 = new Twowords("aa", "bb");
    HashMap<Twowords, Double> transitions = new HashMap<Twowords, Double>();
    System.out.println(tw1.hashCode());
    System.out.println(tw2.hashCode());
    System.out.println(tw3.hashCode());
    if(tw1.equals(tw3)){
    System.out.println("equal");
    }
    transitions.put(tw1, 1.0);
    transitions.put(tw2, 1.0);
    if(transitions.containsKey(tw3)){
    System.out.println("contains!");
    }
    }
    }
    28 条回复    2016-01-18 19:51:52 +08:00
    bigredapple
        1
    bigredapple  
       2016-01-18 09:59:21 +08:00   ❤️ 1
    hashcode
    ilaipi
        2
    ilaipi  
       2016-01-18 09:59:51 +08:00   ❤️ 1
    需要在`Twowords`里面重写 `hashcode()`和`equals()`两个方法
    zts1993
        3
    zts1993  
       2016-01-18 10:07:37 +08:00   ❤️ 1
    不够理解 HashMap 的原理 啊。。。
    beneo
        4
    beneo  
       2016-01-18 10:17:09 +08:00   ❤️ 1
    @ilaipi 说的对
    anonymoustian
        5
    anonymoustian  
    OP
       2016-01-18 10:24:09 +08:00
    @ilaipi 您好,我是重写了的。请问这个写的对吗?
    public int hashCode(){
    return element1.hashCode()+element2.hashCode();
    }
    public boolean equals(Twowords o){
    if(o.hashCode() == this.hashCode()){
    return true;
    }
    return false;
    }
    anonymoustian
        6
    anonymoustian  
    OP
       2016-01-18 10:24:33 +08:00
    @zts1993 你好,我重载了 hashCode 和 equals 方法的。
    public int hashCode(){
    return element1.hashCode()+element2.hashCode();
    }
    public boolean equals(Twowords o){
    if(o.hashCode() == this.hashCode()){
    return true;
    }
    return false;
    }
    fwrq41251
        7
    fwrq41251  
       2016-01-18 10:29:54 +08:00   ❤️ 1
    有用 IDE 吗,eclipse 里面按 alt+shift+s 里面有一项 generate hashCode and equals..
    otakustay
        8
    otakustay  
       2016-01-18 10:30:09 +08:00   ❤️ 1
    HashMap<Twowords, Double> transitions = new HashMap<Twowords, Double>();

    这句看起来是个局部变量,也就是说每次运行代码都创建一个新的 HashMap ,那每次判断 containsKey 的时候这个 HashMap 都是空的,自然是 false ……

    可能你贴出来的代码不全面,所以不好判断原因
    ilaipi
        9
    ilaipi  
       2016-01-18 10:35:59 +08:00   ❤️ 1
    @anonymoustian
    element1 和 element2 是什么类型?
    你的 hashCode 方法,得看你 element 类型的 hashCode 了

    equals 方法这么写可能会出问题的。 3+5=4+4=1+7...

    你网上搜下 hashCode 和 equals 方法的重写,有很多的例子
    anonymoustian
        10
    anonymoustian  
    OP
       2016-01-18 10:39:26 +08:00
    @ilaipi 您好,我把完整代码贴出来了,您能看一下吗?
    anonymoustian
        11
    anonymoustian  
    OP
       2016-01-18 10:39:53 +08:00
    @otakustay 您好,我把完整代码贴出来了,您能看一下吗?
    zacard
        12
    zacard  
       2016-01-18 10:40:10 +08:00   ❤️ 1
    hashcode 和 equals 方法写错了
    anonymoustian
        13
    anonymoustian  
    OP
       2016-01-18 10:41:16 +08:00
    @zacard 您看我写的哪里错了?
    AccIdent
        14
    AccIdent  
       2016-01-18 10:45:49 +08:00   ❤️ 1
    1. hashcode 和 equals 尽量不要自己写,而且你写的有问题
    2. 你的 code 明显不可能有 key 啊, HashMap<Twowords, Double> transitions = new HashMap<Twowords, Double>();//new 的空 hashmap ,后面又没有 put ,能有 key 才有鬼呢

    //话说代码没有格式看着难受
    Infernalzero
        15
    Infernalzero  
       2016-01-18 10:47:24 +08:00   ❤️ 1
    IDE 直接生产下 hashcode 和 equals 方法就行了,你不重写的话就是调用 Object 的了,你每次 new 一个对象当然不等了
    ilaipi
        16
    ilaipi  
       2016-01-18 11:01:49 +08:00   ❤️ 1
    @anonymoustian
    你的测试类的输出结果是?
    anonymoustian
        17
    anonymoustian  
    OP
       2016-01-18 11:03:59 +08:00
    问题解决了。 IDE 生成的 hashcode 和 equals 方法就可以了。谢谢大家!~
    hantsy
        18
    hantsy  
       2016-01-18 11:04:36 +08:00   ❤️ 1
    选择可以 identify 两个对象的一些字段生成相应的 equals 和 hashcode 。
    gy911201
        19
    gy911201  
       2016-01-18 11:55:40 +08:00   ❤️ 1
    问题出在 public boolean equals(Twowords o)上,你实际上没有覆写 equals , 而是重载了它,正确的 equals 只应该传入 Object 类型
    wizardforcel
        20
    wizardforcel  
       2016-01-18 13:51:11 +08:00 via Android   ❤️ 1
    继承自 object 的 hashcode 是按照地址生成的,重新 new 一个当然不成了。

    自己覆写 hashcode ,原理就是每个成员(也可以是部用于标识对象的分成员)的 hashcode 进行一定运算,搜一下就知道怎么做了。
    kaedea
        21
    kaedea  
       2016-01-18 13:59:45 +08:00   ❤️ 1
    看下 containsKey 的源码立刻就知道了
    20015jjw
        22
    20015jjw  
       2016-01-18 15:08:04 +08:00   ❤️ 1
    @ilaipi 俩 key 即使 hashcode 一样 hashmap 也能 handle 的...
    iburu
        23
    iburu  
       2016-01-18 15:31:58 +08:00
    这问题。。。
    slixurd
        24
    slixurd  
       2016-01-18 15:59:48 +08:00
    @20015jjw hashcode 一样的确能处理,大不了就是退化成一条链表
    但是楼主的 hash 和 equals 写的是一样的,那就其实都是逻辑相等了。
    tonic
        25
    tonic  
       2016-01-18 16:34:19 +08:00
    你并没有 `put tw3` 啊... 当然没有...
    henryhuangs
        26
    henryhuangs  
       2016-01-18 17:15:57 +08:00 via iPhone
    equals 里面不要用 hashcode 对比,两个 element.equals 就行,另外 hashCode()里可以调用 apache 的 HashCodeBuilder
    wuyadong
        27
    wuyadong  
       2016-01-18 19:50:47 +08:00
    ..... 要自己先学会找 bug
    MRJ
        28
    MRJ  
       2016-01-18 19:51:52 +08:00
    基础没学好啊,要重写 hashcode 和 equals 方法
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   850 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 20:54 · PVG 04:54 · LAX 12:54 · JFK 15:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.