/ blog / java / cglib-keyfactory.html

Root Beer Logo Root Beer

Chris Nokleberg's Fizzy Weblog

April 2003
Su M Tu W Th F Sa
    3 5
6 7 8 10 11 12
14 15 16 17 19
20 21 22 23 24 25 26
27 28 29 30
Previous  |  Next  |  More...
#  Create multi-object keys with CGLIB

Part II in my very slowly progressing project to get some documentation written.

Have you ever needed to cache data using more than one object as the key? For example, when caching a web page you might use the URL (a String) and the form parameters (a Map). The Java Collections API is not very helpful here. In this situation I would guess that most people would create a two-level Map, but that solution leads to messy code. For instance, when you decide you need to add another object to your key, you have to add a whole other level of nested Maps.

A better solution is to create a new Key class that aggregates all of the key components and properly implements the equals and hashCode methods. For the price of the construction of the key object, you save in lookup speed and memory usage. Overall there can be a noticeable speedup.

Unfortunately is is quite a pain to implement such Key classes. For one thing, implementing a good hashCode method is not trivial. Also, if any of your key objects are arrays, you will be writing a bunch of repetitive and error prone code to loop over every element. Adding another object to the key isn't much easier than when you started, either.

Luckily the monotony of writing these classes lends itself to automation. The CGLIB KeyFactory class can automatically create keys for you that implement proper and efficient hashCode and equals methods:

  • Write an interface that describes your key. This interface should have a single method called "newInstance" that returns an Object, but the argument list can be anything you want.
  • Pass your interface to the KeyFactory create method. It will return to you an object (the "factory") that implements your interface.
  • Whenever you need a new key, call the newInstance method of your factory with the appropriate arguments.

The factory object is generated from byte-code (like everything in CGLIB), and therefore can completely avoid all reflection costs. The hashCode algorithm is adapted from Effective Java by Joshua Bloch, and should give a good distribution, assuming the underlying objects making up your key do too.

[Powered By FreeMarker]  [Valid Atom 1.0]  [Weblog Commenting by]