I ran a little JMH benchmark since this made me curious.
https://gist.github.com/mbien/8f029092749c590878b9b83b8e79fe53
The JVM seems to have some problems to unroll the Objects.hash() method.
Even though It is the least verbose approach, it also makes me less
enthusiastic to switch to it given that
it would be a "generate and forget" situation in both cases where I am not
worried about a few lines more.
But when the hash value is cached -> I would probably use the most compact way
to compute it.
and/or use records of course
(maven 4 made recently some efforts to cache hash constants since not
re-computing them made a
measurable difference there - esp when the tree involved collections)
best regards,
michael
On 11/5/25 23:00, Michael Bien wrote:
> Hi,
>
> The hashCode method generator most likely didn't get updated to use the
> Objects.* utility and does the computation "by hand".
>
> I think this came up on slack before and it would be nice if it could be
> updated to use Objects.hash(...) but nobody got to it so far.
>
> JDK uses a "n = 31*n + obj.hashCode()" loop, NB does the same, just with a
> different prime / start offset and unrolls the loop.
>
> regarding equals: Double.compare() would use Double.doubleToLongBits()
> internally and might be easier to read - something
> NB could change too but its probably not that important.
>
> best regards,
> michael
>
>
> On 11/5/25 22:20, Kenneth Fogel wrote:
>> For a discussion for Java Beans in my writing, I generated the hashCode and
>> equals methods in NetBeans. I then generated the same methods with Eclipse
>> and Intellij. It is the hashCode and equals methods that stood out as
>> Eclipse and Intellij generate the exact same code that is quite different
>> from NetBeans.
>>
>> NetBeans:
>> @Override
>> public int hashCode() {
>> int hash = 3;
>> hash = 97 * hash + Objects.hashCode(this.title);
>> hash = 97 * hash + Objects.hashCode(this.author);
>> hash = 97 * hash + Objects.hashCode(this.publisher);
>> hash = 97 * hash + Objects.hashCode(this.isbn);
>> hash = 97 * hash + this.pages;
>> hash = 97 * hash + this.copiesInStock;
>> hash = 97 * hash + this.copiesSold;
>> hash = 97 * hash + (int)
>> (Double.doubleToLongBits(this.wholesaleCost) ^
>> (Double.doubleToLongBits(this.wholesaleCost) >>> 32));
>> hash = 97 * hash + (int) (Double.doubleToLongBits(this.retailPrice)
>> ^ (Double.doubleToLongBits(this.retailPrice) >>> 32));
>> hash = 97 * hash + (this.suitableForChildren ? 1 : 0);
>> return hash;
>> }
>>
>> Eclipse and IntelliJ:
>> @Override
>> public int hashCode() {
>> return Objects.hash(title, author, publisher, isbn, pages,
>> copiesInStock, copiesSold, wholesaleCost, retailPrice, suitableForChildren);
>> }
>>
>> In NetBeans, why is the initial hash value 3 and then 97 that is always
>> added? Is the fact that 97 + 3 = 100 significant? From the perspective of
>> explaining what this code does, the Eclipse/IntelliJ version is much simpler
>> to describe.
>>
>> Is there a reason for the additional code in the NetBeans version. Is the
>> NetBeans version less prone to false positives, meaning you need to use
>> equals() less often?
>>
>> For the equals() method the difference is also interesting.
>>
>> NetBeans
>> @Override
>> public boolean equals(Object obj) {
>> if (this == obj) {
>> return true;
>> }
>> if (obj == null) {
>> return false;
>> }
>> if (getClass() != obj.getClass()) {
>> return false;
>> }
>> final BookBean other = (BookBean) obj;
>> if (this.pages != other.pages) {
>> return false;
>> }
>> if (this.copiesInStock != other.copiesInStock) {
>> return false;
>> }
>> if (this.copiesSold != other.copiesSold) {
>> return false;
>> }
>> if (Double.doubleToLongBits(this.wholesaleCost) !=
>> Double.doubleToLongBits(other.wholesaleCost)) {
>> return false;
>> }
>> if (Double.doubleToLongBits(this.retailPrice) !=
>> Double.doubleToLongBits(other.retailPrice)) {
>> return false;
>> }
>> if (this.suitableForChildren != other.suitableForChildren) {
>> return false;
>> }
>> if (!Objects.equals(this.title, other.title)) {
>> return false;
>> }
>> if (!Objects.equals(this.author, other.author)) {
>> return false;
>> }
>> if (!Objects.equals(this.publisher, other.publisher)) {
>> return false;
>> }
>> return Objects.equals(this.isbn, other.isbn);
>> }
>>
>> Eclipse and IntelliJ
>> @Override
>> public boolean equals(Object o) {
>> if (o == null || getClass() != o.getClass()) return false;
>> BookBean bookBean = (BookBean) o;
>> return pages == bookBean.pages && copiesInStock ==
>> bookBean.copiesInStock && copiesSold == bookBean.copiesSold &&
>> Double.compare(wholesaleCost, bookBean.wholesaleCost) == 0 &&
>> Double.compare(retailPrice, bookBean.retailPrice) == 0 &&
>> suitableForChildren == bookBean.suitableForChildren && Objects.equals(title,
>> bookBean.title) && Objects.equals(author, bookBean.author) &&
>> Objects.equals(publisher, bookBean.publisher) && Objects.equals(isbn,
>> bookBean.isbn);
>> }
>>
>> In this code Eclipse and IntelliJ use Double.compare for comparing fields
>> that are doubles while NetBeans uses Double.doubleToLongBits.
>>
>> Is this even something to worry about? I am not advocating for this code to
>> be the same in all three IDEs. I would like to know if the differences are
>> significant. From what I see and from my limited understanding about how
>> this code performs, I’d guess the IntelliJ/Eclipse code is superior.
>>
>> Ken
>>
>>
>>
>>
>>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists