content: 
  package com.banrossyn.imageloader.cache.memory.impl;
  
  import android.graphics.Bitmap;
  import com.banrossyn.imageloader.cache.memory.LimitedMemoryCache;
  
  import java.lang.ref.Reference;
  import java.lang.ref.WeakReference;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Map.Entry;
  import java.util.Set;
  
  /**
   * Limited {@link Bitmap bitmap} cache. Provides {@link Bitmap bitmaps} storing. Size of all stored bitmaps will not to
   * exceed size limit. When cache reaches limit size then the bitmap which used the least frequently is deleted from
   * cache.<br />
   * <br />
   * <b>NOTE:</b> This cache uses strong and weak references for stored Bitmaps. Strong references - for limited count of
   * Bitmaps (depends on cache size), weak references - for all other cached Bitmaps.
   *
   * @author rossyn (banrossyn[at]gmail[dot]com)
   * @since 1.0.0
   */
  public class UsingFreqLimitedMemoryCache extends LimitedMemoryCache {
  	/**
  	 * Contains strong references to stored objects (keys) and last object usage date (in milliseconds). If hard cache
  	 * size will exceed limit then object with the least frequently usage is deleted (but it continue exist at
  	 * {@link #softMap} and can be collected by GC at any time)
  	 */
  	private final Map<Bitmap, Integer> usingCounts = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());
  
  	public UsingFreqLimitedMemoryCache(int sizeLimit) {
  		super(sizeLimit);
  	}
  
  	@Override
  	public boolean put(String key, Bitmap value) {
  		if (super.put(key, value)) {
  			usingCounts.put(value, 0);
  			return true;
  		} else {
  			return false;
  		}
  	}
  
  	@Override
  	public Bitmap get(String key) {
  		Bitmap value = super.get(key);
  		// Increment usage count for value if value is contained in hardCahe
  		if (value != null) {
  			Integer usageCount = usingCounts.get(value);
  			if (usageCount != null) {
  				usingCounts.put(value, usageCount + 1);
  			}
  		}
  		return value;
  	}
  
  	@Override
  	public Bitmap remove(String key) {
  		Bitmap value = super.get(key);
  		if (value != null) {
  			usingCounts.remove(value);
  		}
  		return super.remove(key);
  	}
  
  	@Override
  	public void clear() {
  		usingCounts.clear();
  		super.clear();
  	}
  
  	@Override
  	protected int getSize(Bitmap value) {
  		return value.getRowBytes() * value.getHeight();
  	}
  
  	@Override
  	protected Bitmap removeNext() {
  		Integer minUsageCount = null;
  		Bitmap leastUsedValue = null;
  		Set<Entry<Bitmap, Integer>> entries = usingCounts.entrySet();
  		synchronized (usingCounts) {
  			for (Entry<Bitmap, Integer> entry : entries) {
  				if (leastUsedValue == null) {
  					leastUsedValue = entry.getKey();
  					minUsageCount = entry.getValue();
  				} else {
  					Integer lastValueUsage = entry.getValue();
  					if (lastValueUsage < minUsageCount) {
  						minUsageCount = lastValueUsage;
  						leastUsedValue = entry.getKey();
  					}
  				}
  			}
  		}
  		usingCounts.remove(leastUsedValue);
  		return leastUsedValue;
  	}
  
  	@Override
  	protected Reference<Bitmap> createReference(Bitmap value) {
  		return new WeakReference<Bitmap>(value);
  	}
  }
  