Chris Nokleberg's Fizzy Weblog
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:
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.