2

I am working with Hashtable in my java program. I just surprised by seeing the abnormal behavior of Hastable. Below is my code (This is not my final code, i simply created a new simple project with the code which is running abnormal)

    Hashtable<char[], char[]> h1 = new Hashtable<char[], char[]>();
    char[] key = Integer.toString(12).toCharArray();
    char[] val = Integer.toString(21).toCharArray();
    h1.put(key, val);
    System.out.println(h1.containsKey(Integer.toString(12).toCharArray()));// Should print true, since 12 is there in Hashtable
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
ravi
  • 6,140
  • 18
  • 77
  • 154
  • 2
    any specific reason u are using a char[] instead of String? – blejzz Apr 14 '12 at 21:27
  • 1
    possible duplicate of [Using a byte array as HashMap key (Java)](http://stackoverflow.com/questions/1058149/using-a-byte-array-as-hashmap-key-java) – MK. Apr 14 '12 at 21:28
  • You can't even use StringBuffer/Builder as Key in Hashmap https://stackoverflow.com/questions/23790423/string-vs-stringbuffer-as-hashmap-key/23790485#23790485 – Kanagavelu Sugumar Aug 20 '19 at 12:27

3 Answers3

8

You can't use arrays like this as map keys, because arrays have the default, referential-equality-based Object implementations of equals and hashCode. Using String as the key instead would make your program work as desired.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • But I've used arrays of integers. I didn't face any problems. – user Apr 14 '12 at 22:15
  • 2
    @crucified You did, maybe you just didn't notice it.. But since the basic statement ("arrays have referential equality") is true for *any* array, that's just how it is. – Voo Apr 14 '12 at 22:19
  • 3
    @Voo is right. `int[] a = {1}; int[] b = {1}; System.out.println(a == b)` prints `false`. – Louis Wasserman Apr 14 '12 at 22:19
4

Array equality is based on referential equality ("Are these two references to the same object?") not deep equality ("Are these two objects semantically identical?"). Look:

char[] one = Integer.toString(12).toCharArray();
char[] two = Integer.toString(12).toCharArray();
System.out.println(one == two); // false

http://ideone.com/YwEjV

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • They aren't referring to the same object. In my above code, i used `Integer.toString()`. But in my actual code, i am working with `char[]`. So what can be done now? – ravi Apr 14 '12 at 21:28
  • 1
    Use `String`s, not `char[]`s, as map keys. Also, you probably should be using `HashMap` instead of the legacy `Hashtable`. ...Also it would improve the code clarity to write `"12".toCharArray()` or `new char[]{'1', '2'}` instead of `Integer.toString(12).toCharArray()`. – Matt Ball Apr 14 '12 at 21:29
2

if a and b are 2 arrays than a.equals(b) if a == b. So hashCode of a == hashCode of b if a == b. Since this is not the case here, it will not be found in the hashtable. Using arrays as hashtable keys is a bad idea. Also using any mutable object as a hashtable key is a bad idea.

MK.
  • 33,605
  • 18
  • 74
  • 111
  • Your logic is not _completely_ sound, since (in practice) the `.equals()` and `.hashCode()` method implementations are independent. – Matt Ball Apr 14 '12 at 21:36
  • Part of the contract of equals and hashCode is to be consistent between each other. I would assume that Java follows it's own contract. – MK. Apr 14 '12 at 21:40