RFR 8005698 : Handle Frequent HashMap Collisions with Balanced Trees

Peter Levart peter.levart at gmail.com
Sun May 26 11:02:15 UTC 2013


On 05/23/2013 09:02 PM, Brent Christian wrote:
> On 5/23/13 5:20 AM, Doug Lea wrote:
>> * Given that balanced trees are not used in WeakHashMap
>> or Hashtable, I wonder why the TreeNode etc classes are
>> not just nested inside HashMap (usable from subclass LinkedHashMap).
>> And if so, it would be simpler, faster, and less code-intensive
>> to declare TreeNode as a subclass of the internal Entry class.
>> Plus some further gymnastics to overcome the unfortunate
>> decision to make LinkedHashMap a subclass of HashMap.
>> Had you considered this?
>
> I definitely did.  I wanted a cleaner class hierarchy for 
> Entry/TreeNode, but LinkedHashMap makes it difficult, since its 
> Entries need extra before/after references.
>
> I couldn't work out a TreeNode class that could be used by both 
> HashMap and LinkedHashMap, since LHM would need a TreeNode derived 
> from LinkedHashMap.Entry, not HashMap.Entry.
>
> So instead I used composition, where TreeNode has-a 
> [Linked]HashMap.Entry. 

Hi Brent,

It's unfortunate, because composition increases memory footprint. Here's 
my attempt at merging HashMap.Entry with TreeNode into same object:

http://cr.openjdk.java.net/~plevart/jdk8-tl/HM.balancedTrees/merge_TreeNode_and_HashMap_Entry_into_same_object.patch

...this is a patch against your webrev.

Diamond inheritance is solved by making LinkedHashMap.Entry an interface 
and exposing get/set[Before,After] methods instead of before/after 
fields. The hierarchy is as follows:

class HashMap.Entry implements Map.Entry
class TreeNode extends HashMap.Entry
interface LinkedHashMap.Entry extends Map.Entry
class LinkedHashMap.EntryImpl implements LinkedHashMap.Entry
class LinkedHashMap.LinkedTreeNode extends TreeNode implements 
LinkedHashMap.Entry

I also added two factory methods to HashMap which are overriden in 
LinkedHashMap for constructing TreeNode/LinkedHashMap.LinkedTreeNode 
objects.

The TreeNode still contains the final 'entry' field, which is 
initialized to 'this' because there are a lot of references to it. These 
would have to be replaced in code, but would make the patch much larger 
and more difficult to grasp, so I left this exercise for later.

So what do you think? I know that with this patch, the access to 
before/after links in LinkedHashMap.Entry is not direct field access any 
more and goes through invokeinterface and can therefore be slower, 
because there are two implementing classes (LHM.EntryImpl and 
LHM.LinkedTreeNode). But on the other hand, the space savings can be 
noticeable if lots of buckets are transformed into TreeBins...

Regards, Peter




More information about the core-libs-dev mailing list