4

In hibernate manual it is said that you have to override the equals() and hashCode() methods if you intend to put instances of persistent classes in a Set (the recommended way to represent many-valued associations).

So the questions appeared:

  • Why is it a recommended way to represent many-value associations in a set?(Why shouldn't I use, let's say, ArrayList or LinkedList).

  • What happens behind the scene that I should override those methods only when I use Set?

THE Waterfall
  • 645
  • 6
  • 17
  • https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#mapping-model-pojo-equalshashcode – JB Nizet Sep 09 '18 at 15:09
  • 1
    The default `equals` and `hashCode` rely on memory addresses to function (they are good for determining if two variables hold a reference to the same `Object`). But, they don't actually determine anything beyond memory address. Normally you want to change that behavior. – Elliott Frisch Sep 09 '18 at 15:10
  • @ElliottFrisch Yes, you're absolutely right. But I was wondering about peculiarities concerning the rule of overriding those methods only when you use Set but not, for instance, List. – THE Waterfall Sep 09 '18 at 15:22
  • 1
    @THEWaterfall Same issues. The only differences stem from the default behavior. A `HashSet` relies on `hashCode` for bucketing (and `equals` for identity). – Elliott Frisch Sep 09 '18 at 15:24
  • @ElliottFrisch they dont rely on memory for years now https://stackoverflow.com/questions/49172698/default-hashcode-implementation-for-java-objects – Eugene Sep 09 '18 at 15:24
  • 1
    @THEWaterfall it is required for `Set` because of the contractual need to deduplicate elements. It is *a good idea* to do it for List too, in order that things like contains, retainAll, remove etc work as you expect. – Andy Turner Sep 09 '18 at 15:25
  • @ElliottFrisch Fine, you made it clear to me. Didn't come to my mind the idea that HashSet uses hashcode and equals. Thank you. – THE Waterfall Sep 09 '18 at 15:30
  • See also https://stackoverflow.com/a/31455838/545127 – Raedwald Sep 10 '18 at 08:26

2 Answers2

2

Well, how else would a HashSet deduce equality? This is based on hashCode/equals. For a Set you would need both methods, for a List equals is used only ( in a method like contains for example), but they are defined both, so that you don't run in weird surprises.

In general it is a good thing if you override compareTo from Comparable as-well - this is for example used internally for HasMap when a tie is found. You don't have to, but its somehow a good idea, if you ever plan to have these as keys in a Map.

That tie as I said is used when two hashCodes are equals and a HashMap decides to move to a perfectly balanced tree node, see here or this one ; or even this one

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • You should make clear that the tie for which HashMap uses Comparable is in `hashCode`. – Andy Turner Sep 09 '18 at 16:34
  • @AndyTurner there is no requirment indeed, dont know if I have not made that explicit enough, but it is so for when it is tranformed to a red black tree and there is a tie... and an entry has to decide to move to the left or right. I never said a tie when inserting, you assumed that. I also did not say that Comparable has to break equals and hashcode, they must be consistent indeed – Eugene Sep 09 '18 at 16:34
0

Why is it a recommended way to represent many-value associations in a set?(Why shouldn't I use, let's say, ArrayList or LinkedList) -

Many relations are alway unique and there is no point in keeping duplicate values in a collection. As you know set always stores the unique value so Set is recommended to use.

What happens behind the scene that I should override those methods only when I use Set? -

Set stores only unique elements. Set uses Hashmap internally to store the element. So the bucket identification is done with the help of hashCode() and the elements are compared with the help of equals() method.

Saurabh Oza
  • 169
  • 4
  • 18