LRUCache.java [src/csip/utils] Revision: default  Date:
/*
 * $Id$
 *
 * This file is part of the Cloud Services Integration Platform (CSIP),
 * a Model-as-a-Service framework, API and application suite.
 *
 * 2012-2022, Olaf David and others, OMSLab, Colorado State University.
 *
 * OMSLab licenses this file to you under the MIT license.
 * See the LICENSE file in the project root for more information.
 */
package csip.utils;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * LRU cache.
 *
 * @author od
 */
public class LRUCache<K, V> {

  static final int DEFAULT_SIZE = 16;

  Map<K, V> m;
  int size;
  K k;
  V v;


  /**
   * Create a LRU cache,
   * @param size the cache size. A value of 0 disables the cache, a negative
   * value throws an IllegalArgumentException.
   */
  public LRUCache(int size) {
    if (size < 0)
      throw new IllegalArgumentException("size >= 0!");
    m = new LinkedHashMap<>(size);
    this.size = size;
  }


  /**
   * Create a LRU cache with a default cache size of 16.
   */
  public LRUCache() {
    this(DEFAULT_SIZE);
  }


  public V put(K key, V val) {
    if (size == 0 || key == null)
      return null;
    V prev = m.put(k = key, v = val);
    prune();
    return prev;
  }


  public V get(K key) {
    if (size == 0 || key == null)
      return null;
    // accessing the last one again? 
    if (key.equals(k))
      return v;
    if (m.containsKey(key)) {
      V val = m.get(key);
      // remove it from wherever it is in the cache 
      m.remove(key);
      // put it at top
      m.put(k = key, v = val);
      return val;
    }
    return null;
  }


  public void clear() {
    m.clear();
    k = null;
    v = null;
  }


  public void setSize(int size) {
    if (size < 0)
      throw new IllegalArgumentException("cache size: " + size);
    this.size = size;
    prune();
  }


  public int getSize() {
    return size;
  }


  private void prune() {
    while (m.size() > size) {
      // evict element
      K first = m.keySet().iterator().next();
      m.remove(first);
    }
  }

}