1

I have lots of Doubles in my program (notice the capital D) and I was thinking of a possible caching mechanism.

By looking at the Double constructors / factories, none is actually implementing a "cache" (like the way Integer, works, for example when using valueOf).

I was thinking to implement such a cache by using a HashMap<String,Double> where the key is the string representation.

Any visible drawbacks / cons of such implementation?

I wonder why this wasn't done or provided yet by Java.

Bogdan T.
  • 668
  • 6
  • 13
  • What are you trying to achieve? Speedup? – doctorlove Jan 28 '14 at 16:33
  • 1
    Double the storage (at least). Depends on how these Doubles are made, any pattern? – arynaq Jan 28 '14 at 16:33
  • HashMap could cause OutOfMemoryErrors – lance-java Jan 28 '14 at 16:34
  • Presumably the cache mechanism for `Integer` was based on an empirical observation that the values -128 to +127 were used very commonly in many applications. Presumably it was not felt that there would be `Double` values used commonly enough to make the cache mechanism worthwhile, in general. – Oliver Charlesworth Jan 28 '14 at 16:34
  • 4
    Sounds like premature optimization. – Dodd10x Jan 28 '14 at 16:35
  • 2
    [`Double.valueOf`](http://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#valueOf%28double%29) The documentation says it caches common values. Can you explain why this doesn't satisfy what you need? – unholysampler Jan 28 '14 at 16:38
  • @unholysampler -- http://stackoverflow.com/questions/8561710/why-does-the-double-valueof-javadoc-say-it-caches-values-when-it-doesnt] the cache is a lie – Dave L. Jan 28 '14 at 16:39
  • There is an (almost) infinite amount of Doubles between 0 and 1, or even arbitrarily smaller ranges. Which ones would you like to cache? Avoiding `Double` in the first place is not an option? – zapl Jan 28 '14 at 16:40
  • @unholysampler the documentation says it is "likely to", but [the source](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Double.java#Double.valueOf%28double%29) says it doesn't (unless the JVM does some magical memoization of the method on its own, but I doubt that). – MikeFHay Jan 28 '14 at 16:41
  • http://stackoverflow.com/questions/8561710/why-does-the-double-valueof-javadoc-say-it-caches-values-when-it-doesnt, do not trust documentation, trust code – Christophe Roussy Jan 28 '14 at 16:42
  • 1
    Unless you know for certain that your app repeats a small number of doubles a very large number of times, you're probably not helping yourself out much, and could end up hurting things in the long run. Are you going to manage memory such that you track the last time a cached value was requested, purge from the cache, or will the list of doubles you've cached grow forever? A sorted list is better than a map for total memory (slower for performance), but either one sounds like you're introducing an unnecessary complexity and risk. – user1676075 Jan 28 '14 at 16:49

2 Answers2

3

Your problem is that any possible caching mechanism will use far more memory and processor power than you are ever likely to save.

Just think of your example - creating the String, doing the map look-up, garbage collecting the String, etc.

That's a lot more work than just creating a new Double.

The HashMap itself will use a lot of memory.

Considering the number of possible Double values are you going to expire them from the cache somehow or will it keep growing for ever?

It is somewhat telling that the natural key to use into a cache of doubles would be a "new Double" itself (almost certainly faster than the String approach).

You also need to consider equality. For example try in java:

System.out.println((1-0.9)==0.1);

The result is false as the double values generated by each half are different by a miniscule fraction. But if you get a Double from your cache would you want the same Double for (1-0.9) as for (0.1) ?

So you are opening up a massive complicated can of worms, for incredibly tiny savings (in fact you are unlikely to save, most likely you will actually slow things down and use more memory not less).

The only real way to get much better efficiency is just by using double instead of Double (although I realize that's not always possible).

Tim B
  • 40,716
  • 16
  • 83
  • 128
2

Aside from very few values (1.0, 0.0 jump to mind) there isn't such a overwhelming clustering of occurance for small integer values like there is for Integer, so its very hard to come up with a cache that has a reasonable hit rate for common applications.

Second, its not simple to cheaply detect if a Double represents to same value as another, there are edge cases with +0.0, -0.0 and NaN (possibly a few more I didn't think of). Next problem there is no convenient mapping from cached values to a simple cache structure (int maps pretty naturally to Integer[]).

Considering all these problems, there is probably simply no generally worthwhile implementation option for caching of Double values. That doesn't mean you can't come up with one for specialized cases, but before spending time on that you may want to investigate alternatives that are easier to implement / yield potentially better returns (e.g. double instead of Double). If its just that one HashMap, I wouldn't even bother trying to optimize unless it proved to be the bottleneck of my application.

Durandal
  • 19,919
  • 4
  • 36
  • 70