patternjavaMinor
Ugly optimized caching of SimpleDateFormat
Viewed 0 times
cachinguglysimpledateformatoptimized
Problem
Concerning the optimization of this simple function
formatting a
Because of 1., a thread local cache should be used. However, the passed format and arguments may differ from those used in the cache and this must be checked. Funnily, although
Because of 2., the cache must be a static field.
Because of 3., no
This all is pretty restrictive. So I wrote the following ugliness
I don't care about naming and
String formatDate(String format, Locale locale, Date date) {...}formatting a
Date using a SimpleDateFormat created with the arguments format and locale. I'm curious what you thing about the code below. I know it's terrible, but let's assume two things- The code must be as fast as possible.
- There's no suitable object to hold the cache.
- It must not cause any memory leaks.
Because of 1., a thread local cache should be used. However, the passed format and arguments may differ from those used in the cache and this must be checked. Funnily, although
SimpleDateFormat is mutable (which is the cause of all problems), there seem to be no way how to change its format or locale. Actually, the parameters hardly ever change, but there's no guarantee.Because of 2., the cache must be a static field.
Because of 3., no
ThreadLocal.initialValue can be used as it'd lead to memory leaks just like in this question. For the same reason no custom class may be put into the ThreadLocal.This all is pretty restrictive. So I wrote the following ugliness
private String toString(Date obj, String format, Locale locale) {
return getSimpleDateFormat(format, locale).format(obj);
}
private SimpleDateFormat getSimpleDateFormat(String format, Locale locale) {
Object[] list = SDF.get();
// An identity check is faster and correct as missing an entry is allowed.
// It's surely good enough as passing equals but not same parameters hardly ever happens.
if (list!=null && list[0] == format && list[1] == locale) {
return (SimpleDateFormat) list[2];
}
final SimpleDateFormat result = new SimpleDateFormat(format, locale);
list = new Object[] {format, locale, result};
SDF.set(list);
return result;
}
/** Contains triples (String format, Locale locale, SimpleDateFormat sdf) */
private static final ThreadLocal SDF = new ThreadLocal();I don't care about naming and
Solution
What about using a
Also, if I were using a map, I would define a
WeakHashMap? The memory leak is not really an issue since the memory can be reclaimed at any time.Also, if I were using a map, I would define a
FormatAndLocale util class, with valid hashCode and equals, to be used as keys.Context
StackExchange Code Review Q#62208, answer score: 3
Revisions (0)
No revisions yet.