HW 3: Hashing| CS 61B Data Structures, Spring 2019

equals

As mentioned in class, writing a proper equals method is a little tricker than it might sound at first blush. According to the Java language specification, your equals method should have the following properties to be in compliance:

  • Reflexive: x.equals(x) must be true for any non-null x.
  • Symmetric: x.equals(y) must be the same as y.equals(x) for any non-null x and y.
  • Transitive: if x.equals(y) and y.equals(z), then x.equals(z) for any non-null x, y, and z.
  • Consistent: x.equals(y) must return the same result if called multiple times, so long as the object referenced by x and y do not change.
  • Not-equal-to-null: x.equals(null) should be false for any non-null x.

One particularly vexing issue is that the argument passed to the equals method is of type Object, not of type SimpleOomage, so you will need to do a cast. However, doing a cast without verifying that the Object is a SimpleOomage won’t work, because you don’t want your code to crash if someone calls .equals with an argument that is not a SimpleOomage. Thus, we’ll need to use a new method of the Object class called getClass. For an example of a correct implementation of equals, see

 /**
     * Compares this date to the specified date.
     *
     * @param  other the other date
     * @return {@code true} if this date equals {@code other}; {@code false} otherwise
     */
    @Override
    public boolean equals(Object other) {
        if (other == this) return true;
        if (other == null) return false;
        if (other.getClass() != this.getClass()) return false;
        Date that = (Date) other;
        return (this.month == that.month) && (this.day == that.day) && (this.year == that.year);
    }
  1. A Simple hashCode
    In Java, it is critically important that if you override equals that you also override hashCode.

To understand more deeply why this failure occurs, consider the code shown below.

Two questions to ponder when reading this code:

  • What should each print statement output?
  • What will each print statement output?
public void testHashCodeAndEqualsConsistency() {
     SimpleOomage ooA = new SimpleOomage(5, 10, 20);
     SimpleOomage ooA2 = new SimpleOomage(5, 10, 20);

     System.out.println(ooA.equals(ooA2));

     HashSet<SimpleOomage> hashSet = new HashSet<SimpleOomage>();
     hashSet.add(ooA);
     System.out.println(hashSet.contains(ooA2));
 }

Answers:

  • The first print statement should and will output true, according to the definition of equals that we created in the previous part of the assignment.
  • The final print statement should output true. The HashSet does contain a SimpleOomage with r/g/b values of 5/10/20!
  • The final print statement will print false. When the HashSet checks to see if ooA2 is there, it will first compute ooA2.hashCode, which for our code will be the default hashCode(), which is just the memory address. Since ooA and ooA2 have different addresses, their hashCodes will be different, and thus the HashSet will be unable to find an Oomage with r/g/b value of 5/10/20 in that bucket.

The Java specification for equals mentions this danger as well: “Note that it is generally necessary to override the hashCode method whenever the equals method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.”

Note that this hashCode is now consistent with equals, so you should now pass all of the TestSimpleOomage tests.

3.计算hash code 时出现负值

You must convert from hashCode to bucket number using (hashCode & 0x7FFFFFFF) % M or Math.floorMod You should not use Math.abs(hashCode) % M.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值