HashMap中的复合字符串键

Mar*_*eon 2 java key map

我们将一个String键存储在HashMap中,该HashMap是三个String字段和一个布尔字段的串联.问题是如果分隔符出现在字段值中,则可以创建重复键.

所以为了解决这个问题,根据另一篇文章中的建议,我打算创建一个将用作HashMap键的键类:

class TheKey {
  public final String k1;
  public final String k2;
  public final String k3;
  public final boolean k4;

  public TheKey(String k1, String k2, String k3, boolean k4) {
    this.k1 = k1; this.k2 = k2; this.k3 = k3; this.k4 = k4;
  }

  public boolean equals(Object o) {
      TheKey other = (TheKey) o;
      //return true if all four fields are equal
  }

  public int hashCode() {
    return ???;  
  }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 应该从hashCode()返回什么值.该地图将总共包含约30个值.在那些30中,有大约10个不同的k1值(一些条目共享相同的k1值).
  2. 要将此键类存储为HashMap键,是否只需要覆盖equals()和hashCode()方法?还需要什么吗?

Jon*_*eet 12

只是hashCode和equals应该没问题.hashCode看起来像这样:

public int hashCode() {
  int hash = 17;
  hash = hash * 31 + k1.hashCode();
  hash = hash * 31 + k2.hashCode();
  hash = hash * 31 + k3.hashCode();
  hash = hash * 31 + k4 ? 0 : 1;
  return hash;
}
Run Code Online (Sandbox Code Playgroud)

当然,假设没有一个键可以为空.通常,您可以使用0作为上述等式中空引用的"逻辑"哈希码.需要处理空值的复合相等/哈希码的两种有用方法:

public static boolean equals(Object o1, Object o2) {
  if (o1 == o2) {
    return true;
  }
  if (o1 == null || o2 == null) {
    return false;
  }
  return o1.equals(o2);
}

public static boolean hashCode(Object o) {
  return o == null ? 0 : o.hashCode();
}
Run Code Online (Sandbox Code Playgroud)

在这个答案开头的哈希算法中使用后一种方法,你最终得到的结果如下:

public int hashCode() {
  int hash = 17;
  hash = hash * 31 + ObjectUtil.hashCode(k1);
  hash = hash * 31 + ObjectUtil.hashCode(k2);
  hash = hash * 31 + ObjectUtil.hashCode(k3);
  hash = hash * 31 + k4 ? 0 : 1;
  return hash;
}
Run Code Online (Sandbox Code Playgroud)


sta*_*lue 10

在Eclipse中,您可以通过Alt-Shift-S h生成hashCode和equals.