1

I have a class representing a set of values that will be used as a key in maps.

This class is immutable and I want to make it a singleton for every distinct set of values, using the static factory pattern. The goal is to prevent identical objects from being created many (100+) times and to optimize the equals method.

I am looking for the best way to cache and reuse previous instances of this class. The first thing that pops to mind is a simple hashmap, but are there alternatives?

neXus
  • 2,005
  • 3
  • 29
  • 53
  • So those singletons are used as keys in maps? Now you want to make a map to store the keys that you use in other maps? What keys are you going to use to lookup the singletons from the map? Isn't this going in a wrong direction - you first need to lookup a key in a map to be able to use that key to lookup something in another map? – Jesper Aug 24 '10 at 14:41
  • So just what is your caching policy? You want to cache all instances ever created, forever and ever? How many different instances can there be? – polygenelubricants Aug 24 '10 at 15:22
  • @Jesper The singleton contains different fields. It's much easier to work with keys that are single objects. So what I want to do is find the key that is composed of a given set of parameters, or make a new one if no such key exists. Then I can use that single object as a key in a map, which is likely to be faster and cleaner than using a nested map for every sub-key @polygenelubricants They have to be kept for as long as other parts of the application have references to them. – neXus Aug 24 '10 at 15:55
  • 1
    for your cache, you may want to have a map that has soft values then. – polygenelubricants Aug 24 '10 at 16:15

3 Answers3

4

There are two situations:

  • If the number of distinct objects is small and fixed, you should use an enum
    • They're not instantiatiable beyond the declared constants, and EnumMap is optimized for it
  • Otherwise, you can cache immutable instances as you planned:
    • If the values are indexable by numbers in a contiguous range, then an array can be used
      • This is how e.g. Integer cache instances in a given range for valueOf
    • Otherwise you can use some sort of Map

Depending on the usage pattern, you may choose to only cache, say, the last N instances, instead of all instances created so far. This is the approach used in e.g. re.compile in Python's regular expression module. If N is small enough (e.g. 5), then a simple array with a linear search may also work just fine.

For Map based solution, perhaps a useful implementation is java.util.LinkedHashMap, which allows you to enforce LRU-like policies if you @Override the removeEldestEntry.

There is also LRUMap from Apache Commons Collections that implement this policy more directly.

See also

Related questions

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • 2
    To be clear, `Integer#valueOf(int)` cache is [Flyweight pattern](http://en.wikipedia.org/wiki/Flyweight_pattern), not Object pool pattern (the difference is: instances in an object pool are droppable/releasable). – BalusC Aug 24 '10 at 14:57
2

What you're trying to make sounds like an example of the Flyweight Pattern, so looking for references to that might help clarify your thinking.

Storing them in a map of some sort is indeed a common implementation.

Don Roby
  • 40,677
  • 6
  • 91
  • 113
0

What do your objects look like? If your objects are fairly simple I think you should consider not caching them - object creation is usually quite fast. I think you should evaluate whether the possibly small performance boost is worth the added complexity and effort of a cache.

K Erlandsson
  • 13,408
  • 6
  • 51
  • 67