Advertisement
Treyzania

Non-concurrent Generic Cache

Mar 17th, 2016
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.71 KB | None | 0 0
  1. package com.treyzania.test;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Collection;
  5. import java.util.Iterator;
  6. import java.util.List;
  7. import java.util.ListIterator;
  8.  
  9. /**
  10.  * A simple non-concurrent caching mechanism.
  11.  *
  12.  * @author Treyzania
  13.  *
  14.  * @param <T> The type of object stored by this cache.
  15.  */
  16. public class Cache<T> {
  17.  
  18.     private List<Entry<T>> cacheEntries;
  19.     private long cacheTime;
  20.     private int cacheMaxSize;
  21.    
  22.     public Cache(long cachingTime, int maxSize) {
  23.        
  24.         this.cacheTime = cachingTime;
  25.         this.cacheMaxSize = maxSize;
  26.        
  27.         this.cacheEntries = new ArrayList<>();
  28.        
  29.     }
  30.    
  31.     public Cache(long cachingTime) {
  32.         this(cachingTime, Integer.MAX_VALUE);
  33.     }
  34.    
  35.     /**
  36.      * Adds the single item to the cache.
  37.      *
  38.      * @param item
  39.      */
  40.     public void add(T item) {
  41.        
  42.         this.verify();
  43.         this.ensureSpace(1);
  44.        
  45.         this.cacheEntries.add(new Entry<>(System.currentTimeMillis(), item));
  46.        
  47.     }
  48.    
  49.     /**
  50.      * Adds the collection of items to the cache.
  51.      *
  52.      * @param items
  53.      */
  54.     public void addAll(Collection<T> items) {
  55.        
  56.         this.verify();
  57.         this.ensureSpace(items.size());
  58.        
  59.         long time = System.currentTimeMillis();
  60.         for (T item : items) {
  61.             this.cacheEntries.add(new Entry<>(time, item));
  62.         }
  63.        
  64.     }
  65.    
  66.     /**
  67.      * Verifies the cache, then removes the specified number of items from the cache.
  68.      *
  69.      * @param count The number of items removed.
  70.      */
  71.     public void purgeOldest(int count) {
  72.        
  73.         this.verify();
  74.         this.purgeOldest_noVerify(count);
  75.        
  76.     }
  77.    
  78.     private void purgeOldest_noVerify(int count) {
  79.        
  80.         if (count <= 0) return;
  81.        
  82.         // Works as fast as I care to make it.
  83.         this.cacheEntries.removeAll(this.cacheEntries.subList(0, count));
  84.        
  85.     }
  86.    
  87.     /**
  88.      * Ensures that the cache can contain the specified number of items passed by removing old items as necessary.
  89.      *
  90.      * @param count
  91.      * @return The number of items removed.
  92.      */
  93.     public int ensureSpace(int count) {
  94.        
  95.         // Calculate and remove the amount we need to purge.
  96.         int removed = Math.max(0, count + this.size() - this.cacheMaxSize); // TODO Verify this math.
  97.         this.purgeOldest_noVerify(removed);
  98.         return removed;
  99.        
  100.     }
  101.    
  102.     /**
  103.      * Verifies the integrity of the cache, purging old +
  104.      *
  105.      * @return The quantity of items cleared.
  106.      */
  107.     public int verify() {
  108.        
  109.         int removed = 0;
  110.         long currentTime = System.currentTimeMillis();
  111.         Iterator<Entry<T>> iter = this.cacheEntries.iterator();
  112.        
  113.         while (iter.hasNext()) {
  114.            
  115.             Entry<T> entry = iter.next();
  116.            
  117.             if (entry.time + this.cacheTime <= currentTime) {
  118.                
  119.                 removed++;
  120.                 iter.remove();
  121.                
  122.             } else {
  123.                
  124.                 // Since things are stored in order of introduction, we don't need to worry about the rest of the things.
  125.                 break;
  126.                
  127.             }
  128.            
  129.         }
  130.        
  131.         return removed;
  132.        
  133.     }
  134.    
  135.  
  136.     /**
  137.      * @return The current size of the cache.
  138.      */
  139.     public int size() {
  140.         return this.cacheEntries.size();
  141.     }
  142.    
  143.     /**
  144.      * @return An iterator of the values in the cache.
  145.      */
  146.     public Iterator<T> iterator() {
  147.         return new CacheIterator<>(this.cacheEntries.iterator());
  148.     }
  149.    
  150.     /**
  151.      * @return A iterator of the entries in the internal list.
  152.      */
  153.     public ListIterator<Entry<T>> entryIterator() {
  154.         return this.cacheEntries.listIterator();
  155.     }
  156.    
  157.    
  158.     public static class Entry<T> implements Comparable<Entry<T>> {
  159.        
  160.         public final long time;
  161.         public final T value;
  162.        
  163.         private Entry(long time, T value) {
  164.            
  165.             this.time = time;
  166.             this.value = value;
  167.            
  168.         }
  169.        
  170.         @Override
  171.         public int compareTo(Entry<T> o) {
  172.             return (int) Math.signum(Long.compare(this.time, o.time)); // Could possibly be faster.
  173.         }
  174.        
  175.         @Override
  176.         public int hashCode() {
  177.            
  178.             // Auto-generated yuck.
  179.             final int prime = 31;
  180.             int result = 1;
  181.             result = prime * result + (int) (time ^ (time >>> 32));
  182.             result = prime * result + ((value == null) ? 0 : value.hashCode());
  183.             return result;
  184.            
  185.         }
  186.        
  187.         @Override
  188.         public boolean equals(Object obj) {
  189.            
  190.             // Auto-generated yuck.
  191.             if (this == obj)
  192.                 return true;
  193.             if (obj == null)
  194.                 return false;
  195.             if (getClass() != obj.getClass())
  196.                 return false;
  197.             Entry other = (Entry) obj;
  198.             if (time != other.time)
  199.                 return false;
  200.             if (value == null) {
  201.                 if (other.value != null)
  202.                     return false;
  203.             } else if (!value.equals(other.value))
  204.                 return false;
  205.             return true;
  206.            
  207.         }
  208.        
  209.     }
  210.    
  211.     public static class CacheIterator<T> implements Iterator<T> {
  212.        
  213.         private Iterator<Entry<T>> dependency;
  214.        
  215.         private CacheIterator(Iterator<Entry<T>> dep) {
  216.             this.dependency = dep;
  217.         }
  218.        
  219.         @Override
  220.         public boolean hasNext() {
  221.             return this.dependency.hasNext();
  222.         }
  223.  
  224.         @Override
  225.         public T next() {
  226.             return this.dependency.next().value;
  227.         }
  228.        
  229.     }
  230.    
  231. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement