What is the hashCode for a custom class having just two int properties?
You can't change the type of hashCode
, nor should you want to.
I'd just go with something like:
public int hashCode() {
return x * 31 + y;
}
Note that this means that (a, b) is different to (b, a) for most cases (unlike e.g. adding or XOR-ing). This can be useful if you often end up with keys for the "switched" values in real life.
It isn't unique - but hash codes don't have to be. They just have to be the same for equal values (for correctness), and (for efficiency) "usually" different for non-equal values, with a reasonable distribution.
In general, I usually follow the same kind of pattern as Josh Bloch suggests in Effective Java:
public int hashCode() {
int hash = 17;
hash = hash * 31 + field1Hash;
hash = hash * 31 + field2Hash;
hash = hash * 31 + field3Hash;
hash = hash * 31 + field4Hash;
...
return hash;
}
Where field1Hash
would be the hash code for reference type fields (or 0 for a null reference), the int
itself for int values, some sort of hash from 64 bits to 32 for long
etc.
EDIT: I can't remember the details of why 31 and 17 work well together. The fact that they're both prime may be useful - but from what I remember, the maths behind why hashes like this are generally reasonable (though not as good as hashes where the distribution of likely values is known in advance) is either difficult or not well understood. I know that multiplying by 31 is cheap (shift left 5 and subtract the original value)...
I know that it is ok for non-equal objects to have the same hashcodes. However, the more collisions, the worse the performance will be (for example, in a hash table).
As far as I know, the best mapping from Z² → Z is the "elegant pairing function" (google it). Here is the implementation
// x,y must be non-negative
int elegant(int x, int y) {
return x < y ? y * y + x : x * x + x + y;
}
// returns a unique number for every x,y pair
int elegantSigned(int x, int y) {
if (x < 0) {
if (y < 0)
return 3 + 4 * elegant(-x - 1, -y - 1);
return 2 + 4 * elegant(-x - 1, y);
}
if (y < 0)
return 1 + 4 * elegant(x, -y - 1);
return 4 * elegant(x, y);
}
This will begin to overlap as soon as you get multiplication overflow. If the absolute value of x and y is less than about 46000, then this will have zero hash collisions.
This question is quite old, but I think the very idea will be actual as long as java exist. Let us analyze approaches above:
Objects.hash(...)
is fluent and clear what needs to be done, BUT it uses varargs (implicitly creating an array) and moreover, it implicitly boxes every single primitive, being passed into the method.x * 31 + y
is performance-efficient: there is no boxing, no explicit or implicit array creation operations being used. BUT, it is unclear what needs to be done. Why 31, not 42? For the ones familiar with how hashing works there's no difficulties to understand such code, but what for the others? The second pitfall is that it is difficult to extend: you easily can forget to add new values into the hashing code if you, for example, wanted to go 3D and added z coordinate, because it forces you to copy-paste almost identical code many times.
I can introduce the third approach, not being mentioned in answers above:
@Override
public final int hashCode()
{
final int[] numbers = {x, y};
return Arrays.hashCode(numbers);
}
It uses a temporary array to hold integers being hashed, and calling Arrays.hashCode(), which is available since Java 1.5, there's also versions for other primitive types.
Pros: It is DRY, fluent and completely clear what needs to be done. It does not suffer from implicit boxing and does not uses implicit vararg. It is relatively fast and cheap. It can be easily extended by adding extra numbers into array initializer.
Cons: It is not as fast as copy-paste method. Please consider it if hash code is being called frequently.
Best regards.
Just use java.util.Objects.hash(Object... values).
public int hashCode() {
return Objects.hash(field1,field2);
}
Objects.hash actually calls Arrays.hashCode(Object a[])
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}