Atom Feed SITE FEED   ADD TO GOOGLE READER

Coding in the small with Google Collections: Objects.equal and hashCode

Part 4 in a Series.

Objects.equal(Object,Object) and Objects.hashCode(Object...) provide built-in null-handling, which makes implementing your own equals() and hashCode() methods easy.

Before:

  public boolean equals(Object o) {
if (o instanceof Order) {
Order that = (Order)o;

return (address != null
? address.equals(that.address)
: that.address == null)
&& (targetArrivalDate != null
? targetArrivalDate.equals(that.targetArrivalDate)
: that.targetArrivalDate == null)
&& lineItems.equals(that.lineItems);
} else {
return false;
}
}

public int hashCode() {
int result = 0;
result = 31 * result + (address != null ? address.hashCode() : 0);
result = 31 * result + (targetArrivalDate != null ? targetArrivalDate.hashCode() : 0);
result = 31 * result + lineItems.hashCode();
return result;
}


After:

  public boolean equals(Object o) {
if (o instanceof Order) {
Order that = (Order)o;

return Objects.equal(address, that.address)
&& Objects.equal(targetArrivalDate, that.targetArrivalDate)
&& Objects.equal(lineItems, that.lineItems);
} else {
return false;
}
}

public int hashCode() {
return Objects.hashCode(address, targetArrivalDate, lineItems);
}


This is much more concise than handwritten or IDE-generated code. As a special treat, there's deepEquals and deepHashcode methods that 'do the right thing' for arrays and nested arrays, that otherwise use identity for equals and hashCode.

Part 5
Just out of curiosity, aside from not using the builder pattern, are there any significant differences between the google-collections equal and hashCode and the ones from commons-lang?
From a quick look, commons.lang.ObjectUtil is similar to Google's Objects class. But Google's Objects class is more pleasant to use due to use of Java 5 language features like varargs and generics..
There could be undesirable performance impacts of using varargs in the HashCode utility: new Object[] will be created and primitives will be autoboxed. However, the convenience may outweigh those implications for most cases.
Jon, you're right about the varargs having a performance cost on today's VMs. But I expect that optimized varargs will probably show up in the JVM soon.

And as you know, premature optimization is usually misspent. In this case, we can probably use the convenient hashCode() method in 99% of our code, and write a more efficient hashCode() only where our profilers tell us to.
Be careful with BigDecimal and the like though: http://martinaharris.com/2010/02/google-objects-equal-useful-but-be-careful/
Hi Jesse. I found the comments about varargs interesting. I've always noticed that APIs tend to avoid the use of varargs due to a supposed performance penalty. But precisely what is the performance penalty; why is it inefficient? Is it due to the unsolicited allocation of an array? I would be interested to hear your insight on this. Thanks.