Archive for November, 2010

java.util.Hashtable inconcistencies . . .

November 27, 2010

~
I run today into, what seem to me to be, some inconcistencies using java.util.Hashtable, which would not effectively look into the actual values of the String[] in order to search for and identify the same keys.
~
I had previously used java.util.Hashtable heavily, so, unless I am missing something fundamental, I find this behavior really odd.
~
I carefully read the java Hashtable API which is part of the jdk since 1.0
~
http://download.oracle.com/javase/7/docs/api/java/util/Hashtable.html
~
and it does not say anything about arrays or multidimensional objects. Yet is says:
~
“Every key and every value is an object. In any one Dictionary object, every key is associated with at most one value”.
~
and
~
“As a rule, the equals method should be used by implementations of this class to decide if two keys are the same”.
~
but then
~
http://download.oracle.com/javase/7/docs/api/java/lang/Object.html#equals%28java.lang.Object%29
~
uses Object.hashCode()s which apparently only in the case of multidimensional arrays are the same as the System.identityHashCode
~
This is not clearly specified in the API, but to me this is an obvious inconsistency.
~
Why is that? Why is it String objects actual values are being compared but not those values belonging to String[]s?
~
How can you tweak java.util.Hashtables so that they actually use as keys the String[] sequences?
~
I am using:
~

$ java -version
java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Client VM (build 14.2-b01, mixed mode, sharing)

~
based on:
~

$ uname -a
Linux Microknoppix 2.6.31.6 #4 SMP PREEMPT Tue Nov 10 19:11:11 CET 2009 i686 GNU/Linux

~
Here is the test code
~

import java.io.*;
import java.util.*;
import java.text.*;

public class HTblSARI00Test{
// __
public static void main(String[] args){
Integer Itgr;
boolean Is;
int iSysIDHKd, iHshKd;

System.out.println(" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ");
System.out.println("~");
// __ put(ting) aTestSAr (a one dimensional java.lang.String[] array)

Hashtable HTblSARI = new Hashtable();
String[] aTestSAr = new String[]{"abc", "123", "xyz"};
String[] aTestSAr2;

System.out.println("// __ aTestSAr (new String[]{\"abc\", \"123\", \"xyz\"})");

System.out.println("// __ HTblSARI.size(): " + HTblSARI.size());
System.out.println("// __ HTblSARI.put(aTestSAr, HTblSARI.size())");
HTblSARI.put(aTestSAr, HTblSARI.size());
System.out.println("// __ HTblSARI.size(): " + HTblSARI.size());
iHshKd = aTestSAr.hashCode();
System.out.println("// __ aTestSAr.hashCode(): " + iHshKd);
iSysIDHKd = System.identityHashCode(aTestSAr);
System.out.println("// __ System.identityHashCode(aTestSAr): " + iSysIDHKd);
Is = aTestSAr.equals(aTestSAr);
System.out.println("// __ aTestSAr.equals(aTestSAr): " + Is);
Itgr = HTblSARI.get(aTestSAr);
System.out.println("// __ HTblSARI.get(aTestS): " + Itgr);
System.out.println("~");

aTestSAr2 = new String[]{"abc", "123", "xyz"};
System.out.println("// __ aTestSAr2 (new String[]{\"abc\", \"123\", \"xyz\"})");
iHshKd = aTestSAr2.hashCode();
System.out.println("// __ aTestSAr2.hashCode(): " + iHshKd);
iSysIDHKd = System.identityHashCode(aTestSAr2);
System.out.println("// __ System.identityHashCode(aTestSAr2): " + iSysIDHKd);
Is = aTestSAr.equals(aTestSAr2);
System.out.println("// __ aTestSAr.equals(aTestSAr2): " + Is);
Itgr = HTblSARI.get(aTestSAr2);
System.out.println("// __ HTblSARI.get(aTestSAr2): " + Itgr);
System.out.println("// __ HTblSARI.put(aTestSAr2, HTblSARI.size())");
HTblSARI.put(aTestSAr2, HTblSARI.size());
Itgr = HTblSARI.get(aTestSAr2);
System.out.println("// __ HTblSARI.get(aTestSAr2): " + Itgr);
System.out.println("// __ HTblSARI.size(): " + HTblSARI.size());
System.out.println("~");

System.out.println(" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ");
System.out.println("~");

// __ Trying the same thing with a java.lang.String
Hashtable HTblSI = new Hashtable();
String aTestS = "abc";
String aTestS2;
System.out.println("// __ aTestS (\"abc\"): " + aTestS);

System.out.println("// __ HTblSI.size(): " + HTblSI.size());

System.out.println("// __ HTblSI.put(aTestS, HTblSI.size())");
HTblSI.put(aTestS, HTblSI.size());
System.out.println("// __ HTblSI.size(): " + HTblSI.size());

iHshKd = aTestS.hashCode();
System.out.println("// __ aTestS.hashCode(): " + iHshKd);
iSysIDHKd = System.identityHashCode(aTestS);
System.out.println("// __ System.identityHashCode(aTestS): " + iSysIDHKd);
Is = aTestS.equals(aTestS);
System.out.println("// __ aTestS.equals(aTestS): " + Is);
Itgr = HTblSI.get(aTestS);
System.out.println("// __ HTblSI.get(aTestS): " + Itgr);
if(Itgr == null){
HTblSI.put(aTestS, HTblSI.size());
System.out.println("// __ HTblSI.size(): " + HTblSI.size());
}
System.out.println("~");

aTestS2 = "abc";
System.out.println("// __ aTestS2 (\"abc\"): " + aTestS2);
iHshKd = aTestS2.hashCode();
System.out.println("// __ \"abc\".hashCode(): " + iHshKd);
iSysIDHKd = System.identityHashCode(aTestS2);
System.out.println("// __ System.identityHashCode(\"abc\"): " + iSysIDHKd);
Is = aTestS.equals(aTestS2);
System.out.println("// __ aTestS.equals(\"abc\"): " + Is);
Itgr = HTblSI.get(aTestS2);
System.out.println("// __ HTblSI.get(\"abc\"): " + Itgr);
if(Itgr == null){
HTblSI.put(aTestS2, HTblSI.size());
System.out.println("// __ HTblSI.size(): " + HTblSI.size());
}
System.out.println("~");

aTestS2 = (new String("abc".getBytes()));
System.out.println("// __ aTestS2 (new String(\"abc\".getBytes())): " + aTestS2);
iHshKd = aTestS2.hashCode();
System.out.println("// __ (new String(\"abc\".getBytes())).hashCode(): " + iHshKd);
iSysIDHKd = System.identityHashCode(aTestS2);
System.out.println("// __ System.identityHashCode((new String(\"abc\".getBytes()))): " + iSysIDHKd);
Is = aTestS.equals(aTestS2);
System.out.println("// __ aTestS.equals((new String(\"abc\".getBytes()))): " + Is);
Itgr = HTblSI.get(aTestS2);
System.out.println("// __ HTblSI.get((new String(\"abc\".getBytes())): " + Itgr);
if(Itgr == null){
HTblSI.put(aTestS2, HTblSI.size());
System.out.println("// __ HTblSI.size(): " + HTblSI.size());
}
System.out.println("~");

aTestS2 = (new String("abc"));
System.out.println("// __ aTestS2 (new String(\"abc\")): " + aTestS2);
iHshKd = aTestS2.hashCode();
System.out.println("// __ (new String(\"abc\")).hashCode(): " + iHshKd);
iSysIDHKd = System.identityHashCode(aTestS2);
System.out.println("// __ System.identityHashCode((new String(\"abc\"))): " + iSysIDHKd);
Is = aTestS.equals(aTestS2);
System.out.println("// __ aTestS.equals((new String(\"abc\")))): " + Is);
Itgr = HTblSI.get(aTestS2);
System.out.println("// __ HTblSI.get((new String(\"abc\")): " + Itgr);
if(Itgr == null){
HTblSI.put(aTestS2, HTblSI.size());
System.out.println("// __ HTblSI.size(): " + HTblSI.size());
}
System.out.println("~");

aTestS2 = (new StringBuffer("abc").toString());
System.out.println("// __ aTestS2 (new StringBuffer(\"abc\").toString()): " + aTestS2);
iHshKd = aTestS2.hashCode();
System.out.println("// __ (new StringBuffer(\"abc\").toString()).hashCode(): " + iHshKd);
iSysIDHKd = System.identityHashCode(aTestS2);
System.out.println("// __ System.identityHashCode((new StringBuffer(\"abc\").toString())): " + iSysIDHKd);
Is = aTestS.equals(aTestS2);
System.out.println("// __ aTestS.equals(new StringBuffer(\"abc\").toString()): " + Is);
Itgr = HTblSI.get(aTestS2);
System.out.println("// __ HTblSI.get((new StringBuffer(\"abc\").toString())): " + Itgr);
if(Itgr == null){
HTblSI.put(aTestS2, HTblSI.size());
System.out.println("// __ HTblSI.size(): " + HTblSI.size());
}
System.out.println("~");

System.out.println(" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ");
}
}

~
and the result
~

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
// __ aTestSAr (new String[]{"abc", "123", "xyz"})
// __ HTblSARI.size(): 0
// __ HTblSARI.put(aTestSAr, HTblSARI.size())
// __ HTblSARI.size(): 1
// __ aTestSAr.hashCode(): 4072869
// __ System.identityHashCode(aTestSAr): 4072869
// __ aTestSAr.equals(aTestSAr): true
// __ HTblSARI.get(aTestS): 0
~
// __ aTestSAr2 (new String[]{"abc", "123", "xyz"})
// __ aTestSAr2.hashCode(): 1671711
// __ System.identityHashCode(aTestSAr2): 1671711
// __ aTestSAr.equals(aTestSAr2): false
// __ HTblSARI.get(aTestSAr2): null
// __ HTblSARI.put(aTestSAr2, HTblSARI.size())
// __ HTblSARI.get(aTestSAr2): 1
// __ HTblSARI.size(): 2
~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
// __ aTestS ("abc"): abc
// __ HTblSI.size(): 0
// __ HTblSI.put(aTestS, HTblSI.size())
// __ HTblSI.size(): 1
// __ aTestS.hashCode(): 96354
// __ System.identityHashCode(aTestS): 11394033
// __ aTestS.equals(aTestS): true
// __ HTblSI.get(aTestS): 0
~
// __ aTestS2 ("abc"): abc
// __ "abc".hashCode(): 96354
// __ System.identityHashCode("abc"): 11394033
// __ aTestS.equals("abc"): true
// __ HTblSI.get("abc"): 0
~
// __ aTestS2 (new String("abc".getBytes())): abc
// __ (new String("abc".getBytes())).hashCode(): 96354
// __ System.identityHashCode((new String("abc".getBytes()))): 4384790
// __ aTestS.equals((new String("abc".getBytes()))): true
// __ HTblSI.get((new String("abc".getBytes())): 0
~
// __ aTestS2 (new String("abc")): abc
// __ (new String("abc")).hashCode(): 96354
// __ System.identityHashCode((new String("abc"))): 9634993
// __ aTestS.equals((new String("abc")))): true
// __ HTblSI.get((new String("abc")): 0
~
// __ aTestS2 (new StringBuffer("abc").toString()): abc
// __ (new StringBuffer("abc").toString()).hashCode(): 96354
// __ System.identityHashCode((new StringBuffer("abc").toString())): 1641745
// __ aTestS.equals(new StringBuffer("abc").toString()): true
// __ HTblSI.get((new StringBuffer("abc").toString())): 0
~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

~
Thank you
hsymbolicus