HashMap implementations and Integer specializations

charlie hunt charlie.hunt at sun.com
Mon Jun 9 14:57:10 UTC 2008


wrt the Integer & Long values you use in your test case ...

You might consider using larger Integer & Long values, ones that lie 
outside the range of Integer.IntegerCache & Long.LongCache to avoid any 
potential confusion about whether the values you are putting into the 
Map might get grabbed from the IntegerCache or LongCache via some 
"magic" of the HotSpot compiler, i.e it's conceivable a call to 'new 
Integer()' could be transformed into Integer.valueOf()'.

charlie ...

Martin Buchholz wrote:
> JavaOne 2008 technical session PDFs are now available
>
> http://developers.sun.com/learning/javaoneonline/j1online.jsp?track=javase&yr=2008
>
> I was surprised to discover a discussion of
> HashMap optimization at the JavaOne talk
> http://developers.sun.com/learning/javaoneonline/2008/pdf/TS-6434.pdf
>
> Did I miss an announcement of that?
>
> A comment on that talk:
>
> It is easy to make the mistake of thinking that HashMap does not
> have to store the actual Integer key in the call to put.
> Unfortunately, Java's evil semantics (everything is an Object,
> everything is a Lock, everything has an Identity) require
> that the exact same objects inserted into a HashMap can be
> removed later.  This means that specialized submaps will have
> a harder time optimizing for footprint.  (I do think the
> algorithm presented in the talk is correct, since the front cache
> is likely only used for get(), and not, e.g. for entrySet().iterator())
>
> I intend to check in a test case modification that will ensure
> that future optimizations do not violate the current compatibility guarantees.
>
> diff --git a/test/java/util/Collection/MOAT.java
> b/test/java/util/Collection/MOAT.java
> --- a/test/java/util/Collection/MOAT.java
> +++ b/test/java/util/Collection/MOAT.java
> @@ -544,6 +544,27 @@ public class MOAT {
>          check(m.size() != 0 ^ m.isEmpty());
>      }
>
> +    private static void testPutPreversesObjectIdentity(Map<?,?> m,
> +                                                       Object key,
> +                                                       Object val) {
> +        try {
> +            Map<Object,Object> m2 = m.getClass().newInstance();
> +            m2.put(key, val);
> +            Map.Entry<Object,Object> e = m2.entrySet().iterator().next();
> +            check(e.getKey()   == key);
> +            check(e.getValue() == val);
> +            check(m2.keySet().iterator().next() == key);
> +            check(m2.values().iterator().next() == val);
> +        } catch (Throwable t) { unexpected(t); }
> +    }
> +
> +    private static void testPutPreversesObjectIdentity(Map<?,?> m) {
> +        testPutPreversesObjectIdentity(m, new Integer(42),  new Integer(43));
> +        testPutPreversesObjectIdentity(m, new Long(42L),    new Long(43L));
> +        testPutPreversesObjectIdentity(m, new Double(42.0), new Double(43.0));
> +        testPutPreversesObjectIdentity(m, new String("42"), new String("43"));
> +    }
> +
>      private static void testMap(Map<Integer,Integer> m) {
>          System.out.println("\n==> " + m.getClass().getName());
>
> @@ -572,6 +593,7 @@ public class MOAT {
>          }
>
>          if (supportsPut(m)) {
> +            testPutPreversesObjectIdentity(m);
>              try {
>                  check(m.put(3333, 77777) == null);
>                  check(m.put(9134, 74982) == null);
>   

-- 

Charlie Hunt
Java Performance Engineer

<http://java.sun.com/docs/performance/>




More information about the core-libs-dev mailing list