怎样书写一份像样的hashCode()
Java代码中时常需要用到HashMap,与HashMap脱不开关系的便是hashCode()方法,那么怎样书写一份像样的hashCode()成为一个问题。本文将结合《Java编程思想》一书和Java工具类源码,浅谈如何书写一份像样的hashCode()。
-
给int变量result赋予某个非零值常量,如17。
-
为对象内每个有意义的域f(即每个可以做equals()操作的域)计算出一个int散列码c;
域类型 计算 boolean c = (f?0:1) byte、char、short或int c = (int)f float c = Float.floatToIntBits(f) double long l =Double.doubleToLongBits(f) c = (int)(l ^ (l >>> 32)) Object,其equals()调用这个域的equals() c = f.hashCode() 数组 对每个元素应用上述规则 -
合并计算的到的散列码
result = 37 * result + c
-
返回result。
-
检查hashCode()最后生成的结果,确保相同的对象有相同的散列码。
public class CountedString {
private static final List<String> created = new ArrayList<>(10);
private final String s;
private int id = 0;
public CountedString(String string) {
this.s = string;
created.add(string);
for (String s : created) {
if (s.equals(string)) {
id++;
}
}
}
@Override
public String toString() {
return "s='" + s + ''' +
", id=" + id +
", hashcode=" + hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof CountedString &&
s.equals(((CountedString) o).s) &&
id == ((CountedString) o).id;
}
@Override
public int hashCode() {
int result = 17;
result = 37 * result + s.hashCode();
result = 37 * result + id;
return result;
}
public static void main(String[] args) {
Map<CountedString, Integer> map = new HashMap<>();
CountedString[] cs = new CountedString[5];
for (int i = 0; i < cs.length; i++) {
cs[i] = new CountedString("hi");
map.put(cs[i], i);
}
System.out.println(map);
for (CountedString c : cs) {
System.out.println(c);
System.out.println(map.get(c));
}
}
}
输出结果有兴趣的可以自己跑一下代码
以上均参考于《Java编程思想》第四版,陈昊鹏译
在欣赏一下Java自带的关于hashCode的工具方法
// Objects.hashCode(Object o) int
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}
// Objects.hash(Object... values) int
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
// Arrays.hashCode(long a[]) int
public static int hashCode(long a[]) {
if (a == null)
return 0;
int result = 1;
for (long element : a) {
int elementHash = (int)(element ^ (element >>> 2));
result = 31 * result + elementHash;
}
return result;
}
// Arrays.hashCode(int a[]) int
public static int hashCode(int a[]) {
if (a == null)
return 0;
int result = 1;
for (int element : a)
result = 31 * result + element;
return result;
}
// Arrays.hashCode(short a[]) int
...
int result = 1;
for (short element : a)
result = 31 * result + element;
...
// Arrays.hashCode(char a[]) int
...
int result = 1;
for (char element : a)
result = 31 * result + element;
...
// Arrays.hashCode(byte a[]) int
...
for (byte element : a)
...
// Arrays.hashCode(boolean a[]) int
...
for (boolean element : a)
result = 31 * result + (element ? 1231 : 1237);
...
// Arrays.hashCode(float a[]) int
...
for (float element : a)
result = 31 * result + Float.floatToIntBits(element);
...
// Arrays.hashCode(double a[]) int
...
for (double element : a) {
double bits = Double.doubleToLongBits(element);
result = 31 * result + (int)(bits ^ (bits >>> 32));
}
...
// Arrays.hashCode(Object a[]) int
...
for (Object element : a) {
Object bits = Double.doubleToLongBits(element);
result = 31 * result + (int)(bits ^ (bits >>> 32));
}
...
// Arrays.deepHashCode(Object a[]) int
// 该方法是关于多维数组的散列值方法,具体可查看响应源码