0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Effective Javaを読む】 第3章 項目9 『equalsをオーバーライドする時は、常にhashCodeをオーバーライドする』

Last updated at Posted at 2020-07-31

#equalsをオーバーライドする時は、常にhashCodeをオーバーライドする

equalsをオーバーライドしているすべてのクラスは、一緒にhashCodeもオーバーライドしなければObject.hashCodeの一般契約を破ってしまうよ、というお話

##サンプルコード

以下のコードはequalsはオーバーライドしていますが
hashCodeはオーバーライドしていません

例1
public final class PhoneNumber {
    private final short areaCode;
    private final short prefix;
    private final short lineNumber;

    public PhoneNumber(int areaCode, int prefix,
                       int lineNumber){
        rangeCheck(areaCode, 999, "area code");
        rangeCheck(prefix, 999, "prefix");
        rangeCheck(lineNumber, 9999, "line number");
        this.areaCode = (short)areaCode;
        this.prefix = (short)prefix;
        this.lineNumber = (short)lineNumber;
    }

    private static void rangeCheck(int arg, int max, 
                                   String name){
        if (arg < 0 || arg > max)
            throw new IllegalArgumentException(name +": " + arg);
    }

    @Override public boolean equals(Object o){
        if (o == this)
            return true;
        if (!(o instanceof PhoneNumber))
            return false;
        PhoneNumber pn = (PhoneNumber)o;
        return pn.lineNumber == lineNumber
            && pn.prefix == prefix
            && pn.areaCode == areaCode;
    }

    // 不完全 - hashCodeメソッドがない!
    
    ... // 残りは省略
}

例1をHashMapで使用することを想定してみる。
例2でm.get(new PhoneNumber(707, 867, 5309))"Jenny"を返すと期待されるけれども、帰ってくるのはnullです。
hashCodeをオーバーライドしていないので、putしたPhoneNumberとgetしているPhoneNumberはハッシュ値が別物だからです。

例2
Map<PhoneNumber, String> m = new HashMap<PhoneNumber, String>();
m.put(new PhoneNumber(707, 867, 5309), "Jenny");

以下はあくまで例ですがhashCodeをオーバーライドしてあげましょう。

例3

@Override public int hashCode(){
    int result = hashCode;
    if (result == 0){
        result = 17;
        result = 31 * result + areaCode;
        result = 31 * result + prefix;
        result = 31 * result + lineNumber;
        hashCode = result;
    }
    return result;
}

#続く
【Effective Javaを読む】 第3章 項目10 『toStringを常にオーバーライドする』
https://qiita.com/Natsukii/items/6e2cd2e77e144048819d

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?