6

I'm having two lists of objects, users and products

users own products, and each products is associated to 1 user

but a product type can be multiple and be owned by separate users

  • users: Ed, Rob
  • products: Coca, Sprites(1), Sprites(2), Beer
  • Ed has Coca and Sprites(1), Rob Sprites (2) and Beer

I need to generate an id for each unique (user+product)

It's probably not a good idea to do

user.hashCode() + product.hashCode()

What could be a good way to proceed?

Péter Török
  • 114,404
  • 31
  • 268
  • 329
  • Related: http://stackoverflow.com/questions/2587442/hash-code-for-a-group-of-three-fields – Thilo Apr 20 '12 at 09:35
  • 2
    `(37*(17 + user.hashCode) + product.hashCode())`. Taken from Effective Java. – Marko Topolnik Apr 20 '12 at 09:38
  • 3
    Hashcodes are not unique. Equal objects return the same hashcode, but the same hashcode does not mean that objects are equal. Don't mistake hashcode for an ID. – Noel M Apr 20 '12 at 09:39

3 Answers3

7

Your hashCode is not that bad if both user and product create pseudo-random hash-codes. If you are afraid of hash collisions because of bad hashCode implementations in either user or product, then multiply one of the source hash codes by a prime number:

public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((product == null) ? 0 : product.hashCode());
  result = prime * result + ((user == null) ? 0 : user.hashCode());
  return result;
}

Eclipse builds this very code when selecting Source | Generate hashCode() and equals().

As mentioned by Thilo, you can also simply use Arrays.hashCode(new Object[]{ user, product }); This call takes care of null values for user or product and also multiplies the result by 31 - same as the hand written code. If you are using Google Guava, there is an Objects.hashCode(Object...) that makes your intent a little bit clearer and uses varargs, but it also only delegates to Arrays.hashCode.

nd.
  • 8,699
  • 2
  • 32
  • 42
  • so here you are using the same prime number as multiplier of user and product, why don't take 2 different ones? –  Apr 20 '12 at 10:32
  • 1
    @ca11111 there is already a post at stackoverflow that answers this much better than I ever could: http://stackoverflow.com/a/1147232/112964 – nd. Apr 20 '12 at 11:35
5

You could let Apache Commons HashCodeBuilder do the work for you.

It lets you write something like

return new HashCodeBuilder(17, 37).
   append(user).
   append(product).
   toHashCode();
DerMike
  • 15,594
  • 13
  • 50
  • 63
1

A common solution is to multiply the first hash with a prime number and then add the second hash.

bongi
  • 116
  • 1