-4

I created a HashSet of Integers (Ex. 5). When I try to check the HashSet for the same added element but in a Double element version (Ex. 5d, 5.0). It couldn't identify and returns false!

My assumption was, Java would implicitly convert Double to Integer and try to identify. But it didn't! Why is this the case?

    Set<Integer> set = new HashSet<Integer>();
    set.add(5);

    System.out.println(set.contains(5d)); // returns false? Why?
    System.out.println(set.contains(5.0));// returns false? Why?
    System.out.println(set.contains(5));  // returns true
    System.out.println(5 == 5d);          // returns true
william cage
  • 429
  • 1
  • 4
  • 18
  • No it doesn't. The other questions accepted answer says Java does type comparison within HashMap. But I don't see a type comparison done within HashMap containsKey method. – william cage Mar 05 '22 at 01:42
  • To put it in terms of the other answer: these cases return `false` because `Integer.valueOf(5).equals(Double.valueOf(5))` is `false`. – Joe Mar 05 '22 at 01:48

1 Answers1

3

HashSet.contains takes an Object as parameter (so, basically anything). 5.0 is a double so it gets autoboxed to a Double, and your HashSet only contains Integer values, which never compare .equals to a Double.

Even if HashSet.contains took an Integer as argument, Java would reject your code. In general, Java is pretty stingy about implicit conversions and will only do so if there's no loss of precision. So it will happily convert, say, an int to a long without asking, but it's way more careful about converting a double to an int or to an Integer.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • so you are saying it will compare the object type first, before comparing the value? which means it will first do something like Double == Integer and it will fail? – william cage Mar 05 '22 at 01:33
  • Exactly. `Double.equals` will get called, and the first thing that method does is check the type of the right-hand-side. – Silvio Mayolo Mar 05 '22 at 01:37
  • I am respectfully disagreeing to your answer. I did a debug through inside HashSet contains method. I don't see Double.equals getting called. – william cage Mar 05 '22 at 01:45
  • It returns false in the below if condition within getNode method in HashMap. if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) And I don't understand what this means – william cage Mar 05 '22 at 01:47
  • @williamcage _"I don't see Double.equals getting called"_ -- that is correct, because it's a `HashSet`, thus it will be `Integer#equals()` that is called. It also checks the type of the other object and returns false if the types are not the same. For it to work, you MUST pass an `Integer` to the `.contains()` method, which you can get via `doubleVariable.intValue()` (with appropriate truncation if the value is not actually an integer). – Jim Garrison Mar 05 '22 at 01:58
  • I put a breakpoint in Integer#equals() as well. This method is not getting called. – william cage Mar 05 '22 at 02:24
  • 4
    @williamcage The "Hash" in HashSet is relevant here. `equals` isn't invoked at all until first the hashes are equal. 5.0D the double has a different hash value than 5, the integer. Hence you never get to `equals` in the first place. `Double.valueOf(5.0D).hashCode()` and `Integer.valueOf(5).hashCode()` - compare those. – rzwitserloot Mar 05 '22 at 02:25
  • @rzwitserloot, thanks. this is the sort of direction I am looking. But, how is this hash comparison done? It is failing in this condition if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) within HashMap. How is this relating to the hash comparison? – william cage Mar 05 '22 at 02:29
  • 1
    @william The hash is used to index into the "table" (i.e. array). That's typical hash table stuff. If it doesn't find anything in the "bucket" then it knows immediately it does not contain the element. If there _is_ something in the bucket then it will compare the objects via `equals`. Note that Java's `HashSet` handles hash collisions by using a linked list, until a certain threshold is reached, where it changes over to a tree structure. – Slaw Mar 05 '22 at 02:51