package org.lodder.subtools.sublibrary.cache;

import java.util.ArrayList;

import org.apache.commons.collections4.MapIterator;
import org.apache.commons.collections4.map.LRUMap;

/**
 * @author Crunchify.com
 */

public class InMemoryCache<K, T> {

  private long timeToLive;
  @SuppressWarnings("rawtypes")
  protected LRUMap cacheMap;

  @SuppressWarnings("rawtypes")
  public InMemoryCache(long crunchifyTimeToLive, final long crunchifyTimerInterval, int maxItems) {
    this.timeToLive = crunchifyTimeToLive * 1000;

    cacheMap = new LRUMap(maxItems);

    if (timeToLive > 0 && crunchifyTimerInterval > 0) {
      createCleanUpThread(crunchifyTimerInterval);
    }
  }

  private void createCleanUpThread(final long timerInterval) {
    Thread t = new Thread(new Runnable() {
      public void run() {
        while (true) {
          try {
            Thread.sleep(timerInterval * 1000);
          } catch (InterruptedException ex) {}
          cleanup();
        }
      }
    });

    t.setDaemon(true);
    t.start();
  }

  @SuppressWarnings("unchecked")
  public void put(K key, T value) {
    synchronized (cacheMap) {
      cacheMap.put(key, new CacheObject<K, T>(value));
    }
  }

  @SuppressWarnings("unchecked")
  public T get(K key) {
    synchronized (cacheMap) {
      CacheObject<K, T> c = (CacheObject<K, T>) cacheMap.get(key);

      if (c == null)
        return null;
      else {
        c.lastAccessed = System.currentTimeMillis();
        return c.value;
      }
    }
  }

  public void remove(K key) {
    synchronized (cacheMap) {
      cacheMap.remove(key);
    }
  }

  public int size() {
    synchronized (cacheMap) {
      return cacheMap.size();
    }
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  public void cleanup() {

    long now = System.currentTimeMillis();
    ArrayList<K> deleteKey = null;

    synchronized (cacheMap) {
      MapIterator itr = cacheMap.mapIterator();

      deleteKey = new ArrayList<K>((cacheMap.size() / 2) + 1);
      K key = null;
      CacheObject<K, T> c = null;

      while (itr.hasNext()) {
        key = (K) itr.next();
        c = (CacheObject<K, T>) itr.getValue();

        if (c != null && (now > (timeToLive + c.lastAccessed))) {
          deleteKey.add(key);
        }
      }
    }

    for (K key : deleteKey) {
      synchronized (cacheMap) {
        cacheMap.remove(key);
      }

      Thread.yield();
    }
  }
}

package org.lodder.subtools.sublibrary.cache;

import java.util.ArrayList;

import org.apache.commons.collections4.MapIterator;
import org.apache.commons.collections4.map.LRUMap;

/**
 * @author Crunchify.com
 */

public class InMemoryCache<K, T> {

  private long timeToLive;
  @SuppressWarnings("rawtypes")
  protected LRUMap cacheMap;

  @SuppressWarnings("rawtypes")
  public InMemoryCache(long crunchifyTimeToLive, final long crunchifyTimerInterval, int maxItems) {
    this.timeToLive = crunchifyTimeToLive * 1000;

    cacheMap = new LRUMap(maxItems);

    if (timeToLive > 0 && crunchifyTimerInterval > 0) {
      createCleanUpThread(crunchifyTimerInterval);
    }
  }

  private void createCleanUpThread(final long timerInterval) {
    Thread t = new Thread(new Runnable() {
      public void run() {
        while (true) {
          try {
            Thread.sleep(timerInterval * 1000);
          } catch (InterruptedException ex) {}
          cleanup();
        }
      }
    });

    t.setDaemon(true);
    t.start();
  }

  @SuppressWarnings("unchecked")
  public void put(K key, T value) {
    synchronized (cacheMap) {
      cacheMap.put(key, new CacheObject<K, T>(value));
    }
  }

  @SuppressWarnings("unchecked")
  public T get(K key) {
    synchronized (cacheMap) {
      CacheObject<K, T> c = (CacheObject<K, T>) cacheMap.get(key);

      if (c == null)
        return null;
      else {
        c.lastAccessed = System.currentTimeMillis();
        return c.value;
      }
    }
  }

  public void remove(K key) {
    synchronized (cacheMap) {
      cacheMap.remove(key);
    }
  }

  public int size() {
    synchronized (cacheMap) {
      return cacheMap.size();
    }
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  public void cleanup() {

    long now = System.currentTimeMillis();
    ArrayList<K> deleteKey = null;

    synchronized (cacheMap) {
      MapIterator itr = cacheMap.mapIterator();

      deleteKey = new ArrayList<K>((cacheMap.size() / 2) + 1);
      K key = null;
      CacheObject<K, T> c = null;

      while (itr.hasNext()) {
        key = (K) itr.next();
        c = (CacheObject<K, T>) itr.getValue();

        if (c != null && (now > (timeToLive + c.created))) {
          deleteKey.add(key);
        }
      }
    }

    for (K key : deleteKey) {
      synchronized (cacheMap) {
        cacheMap.remove(key);
      }

      Thread.yield();
    }
  }
}

Use created to preform clean up