java中一年和一月元组的好hashCode是什么

时间:2018-03-12 18:15:21

标签: java equals hashcode

在Java中,我们说我有很长的年和月对列表。像2018:03那样有很多重复。

Month will always be starting with 1.
Year will always be > Month, starting with 2010
if Month or Year == 0 [not_set], hashcode can return 0 (fine), I ignore them

我想遍历此列表并为每个条目的这两个值创建一个哈希,以确定我是否已经有一个特定的组合。

通常我会为这样的一个条目创建一个Object,它有两个int成员并覆盖equals和hashcode,将它们全部添加到一个Set中。

我应该如何实现hashCode?

据我记得有效的java,我会写一些类似的东西:

@Override
public int hashCode() {
    int hash = year;
    hash = 31 * hash + month;
    return hash;
}

但我认为,因为月份总是小于一年,在这种情况下我很擅长:

@Override
public int hashCode() {
    return year * month;
}
直到4020年,不应发生任何碰撞。

有没有更有效的方法来实现我的目标,你能想到吗? 或者已经太晚了,我的脑袋正在分崩离析?

3 个答案:

答案 0 :(得分:3)

只要它满足hashCode的{​​{3}},它应该是一个很好的哈希码实现:

  
      
  • 每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终如一   返回相同的整数,前提是equals中没有使用的信息   对象的比较被修改。不需要保留该整数   从一个应用程序的执行到另一个执行的一致性   相同的申请。
  •   
  • 如果两个对象根据equals(Object)方法相等,则必须对两个对象中的每一个调用hashCode方法   产生相同的整数结果。
  •   
  • 如果两个对象根据equals(java.lang.Object)方法不相等,则不需要调用hashCode方法   两个对象中的每一个都必须产生不同的整数结果。   但是,程序员应该意识到产生了不同的   不等对象的整数结果可以提高性能   哈希表。
  •   

实施hashCode方法的另一种方法是调用Objects.hash

return Objects.hash(year, month);

答案 1 :(得分:2)

正如您已经提到的Effective Java [1],这是从同一本书中创建一个好的哈希函数的方法:

  
      
  1. 声明一个名为result的int变量,并将其初始化为对象中第一个重要字段的哈希码c

  2.   
  3. 对于对象中每个剩余的重要字段f,请执行以下操作:

         

    一个。计算字段的int哈希码c:

  4.         

    我。如果该字段是基本类型,则计算Type.hashCode(f),其中Type是与f的类型对应的盒装基元类。

         

    II。如果该字段是一个对象引用,并且该类的equals方法通过递归调用equals来比较该字段,则在该字段上递归调用hashCode。如果需要更复杂的比较,则为该字段计算“规范表示”并在规范表示上调用hashCode。如果字段的值为null,则使用0(或其他常量,但传统的0)。

         

    III。如果该字段是数组,则将其视为每个重要元素都是单独的字段。也就是说,通过递归地应用这些规则来计算每个重要元素的哈希码,并组合每个步骤2.b的值。如果数组没有重要元素,则使用常量,最好不要为0.如果所有元素都很重要,请使用Arrays.hashCode。

         

    湾将步骤2.a中计算的哈希码c组合到结果中,如下所示:

         

    结果= 31 *结果+ c;

         
        
    1. 返回结果。
    2.   

将此食谱翻译成您的食谱:

@Override
public int hashCode() {
  int hash = Integer.hashCode(year);
  hash = 31 * hash + Integer.hashCode(month);
  return hash;
}

[1] Effective Java,Third Edition(http://www.informit.com/store/effective-java-9780134685991

答案 2 :(得分:0)

您可以查看Java 8的java.time.YearMonth code(或equivalent class in ThreenTen Backport,Java< = 7)。两者都使用:

public int hashCode() {
    return year ^ (month << 27);
}