Wednesday, July 2, 2014

A little tip about equals() and hashCode()


Don't forget to check if equals() and hashCode() are overriden in any class (unless you use String or class that you're very familiar with) you use in collection!

And a little story about that...

Several days ago I tried to fix a memory leak somewhere in LruCache. LruCache provides a way to cache some objects while they're not exceeding a particular amount of memory. After that the oldest object in the cache is not being hold any more and available for garbage collector.

LruCache isn't a collection itself, but it should contain a map inside (and it does, have a look at the source code here) for key to value mapping (where the value is a cached object you need), so any class you use as key for LruCache should contain overridden equals() and hashCode().

But, unlucky for me, I used ResolveInfo as the key (and application icon as a value). Although it looks like a pretty simple data structure, it doesn't contain equals() and hashCode() overridden, I don't see the reason why - you can look here if you don't believe me.

So instead of caching it simply stored my icons and sometimes garbage collector couldn't do anything before OutOfMemoryError was throwed.

In my case, I replaced ResolveInfo to my own class that contains two fields: resolveInfo.activityInfo.packageName and resolveInfo.activityInfo.name and ultimately override equals() and hashCode(). Pair class is useful for such purposes too (and I actually copied equals() and hashCode() implementation from there) but it's always better to use more meaningful names.

Have a nice day!

P.S. Be careful to update to ADT 23.0.0 - it ruined my Eclipse and I needed to download the whole ADT Bundle for clean install. See here for details.