8

I always thought that enum hashCode was referring to ordinal in Java, since ordinal seems to be a perfect candidate for hashCode, but it turns out it enum hashCode actually refers to default hashCode object implementation.

I understand, that this does not contradict JLS, but still this came to me as a surprise, and I can't think why it was made this way. Although I guess JVM, could have relied on this somehow to provide unique guarantees, but this does not hold anymore for 64 bit JVM.

I've checked in JDK 1.6, and latest JDK 7, and this is the same way in both.

Does any one know reason why, it was made this way?

It makes a perfect sense to use ordinal as a hashCode, since it satisfies all the credentials needed plus it is even consistent from one JVM start to the other, which is not required, but nice thing to have.

mavarazy
  • 7,562
  • 1
  • 34
  • 60
  • Unless you happen to get a response from a JDK author the answer is basically 'no'. Not real question. – user207421 Mar 06 '13 at 08:54
  • @EJP I don't think you need a jdk author to understand the difference between hashcode and enum ordinal. – NimChimpsky Mar 06 '13 at 08:58
  • 1
    I have a perfect understanding of difference betqween hashCode and ordinal, what I don't understand is why are they different in case of enum, it makes a perfect sense to use ordinal as a hashCode, since it satisfies all the credentials needed plus it is even consistent from one JVM start to the other, which is not required, but nice. – mavarazy Mar 06 '13 at 10:00
  • 1
    @anton_oparin "I have a perfect understanding of difference betqween hashCode and ordinal" you don't hence the question, and clear answers.Using ordinal would guarantee collisions, whereas hashcode implementations avoid them – NimChimpsky Mar 06 '13 at 10:01
  • Ordinal is unique. So what collisions? If it's unique there are no collisions, if it's used as is. If you use hashCode as location, collisions are more likely. – mavarazy Mar 06 '13 at 10:05
  • 1
    @anton_oparin Ordinal is not unique!!! Look at the answer given by perception, the ordinal of both is 0, they are the first in each enum declaration – NimChimpsky Mar 06 '13 at 10:15
  • It is unique for given Enum. Default HASHCODE can be considered unique only in 32 bit JVM, if we consider all Objects do not use hashCode implementation at all, if 64 bit JVM used HASHCODE would repeat itself even under this condition ... I have a feeling you are doing it on purpose ... – mavarazy Mar 06 '13 at 10:33
  • It is unique for given enum .. so ? That is irrelevant. – NimChimpsky Mar 06 '13 at 10:39

2 Answers2

8

Imagine this trivial, completely made up scenario:

interface MediaType {}

enum BookTypes implements MediaType {
    HARDCOVER;
}

enum MagazineTypes implements MediaType {
    MONTHLY;
}

Map<MediaType, MediaItem> itemMap = new HashMap<MediaType, MediaItem>();
itemMap.put(BookTypes.HARDCOVER, new Book());
itemMap.put(MagazineTypes.MONTHLY, new Magazine());

I think it's pretty clear why you wouldn't want to use ordinal as a hash code in this instance.

Perception
  • 79,279
  • 19
  • 185
  • 195
  • Since enum uses default hashCode, there can be cases, when the same enum used as key, gets in the same bucket in HashMap, this could happen randomly or systematically, depending on the structure of enum. So your point is not valid. – mavarazy Mar 06 '13 at 09:53
  • 3
    The chance for collisions is ***much*** higher using the ordinal as hash code, as opposed to using the default hash code, which is optimized and has *very* few collisions. My point is quite valid. – Perception Mar 06 '13 at 09:57
  • *much* higher is an understatement, they are guaranteed. – NimChimpsky Mar 06 '13 at 09:59
  • @NimChimpsky - well by the specification its not guaranteed. Though I have not seen an implementation in the wild yet that did not return unique hash codes for objects. It's definitely possible to run into conflicts in long running apps that use PRNG's to allocate hash codes. But in any case its still *highly* unlikely. – Perception Mar 06 '13 at 10:07
  • @Perception I meant collisions would be guaranteed if ordinal is used – NimChimpsky Mar 06 '13 at 10:13
  • @NimChimpsky - ah gotcha. Yes, I agree. – Perception Mar 06 '13 at 10:20
  • Actually, you can get at most as many items with the same `hashCode` as many different enums classes you put in, i.e., typically one, i.e., no collisions. Cases when multiple different enums are mixed in a single collection are pretty rare, so it's not IMHO as bad as needless collisions for short strings (though I've never seen any corresponding figures). – maaartinus Jun 19 '19 at 22:48
3

hashcode and ordinal are completely different.

The first instance of every enum would have the same ordinal value, the opposite of a hashcode.

ordinal() Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero).

enum BookTypes implements MediaType {
    HARDCOVER;  //ordinal is 0
}

enum MagazineTypes implements MediaType {
    MONTHLY; //ordinal is 0
}
NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
  • This is true, and as I am saying it does not contradict JLS, but, again, ordinal seems to be a perfect candidate for hashCode, and I can't think of the reason why it was not used as such. – mavarazy Mar 06 '13 at 09:56
  • @anton_oparin you are totally missing the point, ordinal is not a perfect candidate at all, for the reason i put in my scond line, and also in the other answer. – NimChimpsky Mar 06 '13 at 09:57
  • UNIQUE VALUE IS A PERFECT CANDIDATE FOR HASH CODE, ORDINAL IS UNIQUE FOR ENUM. One over fetched example does not make a case. – mavarazy Mar 06 '13 at 10:25
  • 1
    @anton_oparin its not an overfecthed example - its just two enums, I have about 25 in one of my apps. Using your method, their hashcodes would all collide, thus making the hashcode compeletely useless. Ordinal would be a perfect candidate for hashcode, if you can guarantee you only have one enum in your entire application, which would be stupid. – NimChimpsky Mar 06 '13 at 10:38
  • @NimChimpsky OK, the ordinal-based hashcodes of the corresponding members of your enums would all collide, but do you have a place where this matters? Some `Set` or maybe `Set` where you really put members of different enums? – maaartinus Nov 02 '16 at 22:23