2014-09-06 86 views
-1

我将在类级别声明一个ArrayList。我将使用'set'方法来为数组填充值。这个'set'方法将从一个ActionEvent方法中调用。事件会在程序中定期发生,所以这个'set'方法将被调用100次或更多。每次'set'被调用时,它都会传递一个String变量给set方法。 String变量将被添加到(Class level)ArrayList中。我想让这个ArrayList“修剪”自己,以便它只包含5个值。即:我需要索引4处的值被消除,索引3处的索引转换为索引4,并且传入的“最新”变量变为索引0.我不知道该怎么做是让ArrayList“修剪“本身就是这样。一些指导意见会非常赞赏。谢谢xxx如何“修剪”一个arrayList只有5个最近的值? :

回答

3

ArrayList对于你需要做的事不是一个合适的类。你基本上需要一个有限的容量circular buffer - ArrayDeque会更接近。你必须把它扩大,但是,为了拥有它含蓄地下降元素时,它的容量已经达到:

public static class LimitedArrayDeque<T> extends ArrayDeque<T> { 
    int threshold; 

    public LimitedArrayDeque(int capacity) { 
     super(capacity); 

     this.threshold = capacity - 1; 
    } 

    @Override 
    public boolean add(T element) { 
     while (this.size() > this.threshold) { 
      this.removeFirst(); 
     } 

     return super.add(element); 
    } 

    /* ... */ 
} 

请注意,你应该重写添加元素到队列中相同的方式add()任何方法在我的例子中。

+0

你想在'removeFirst'之前执行'add',以防'add'失败。 – 2014-09-06 07:11:25

+0

@ chiastic-security:这是一个语义问题 - 如果你这样做,那么很短的时间内,队列的容量已经超过了...... – thkala 2014-09-06 07:12:24

+0

确实如此。另一方面,如果你的方向是朝着你的方向发展,那么一段时间内它的容量不足,并且不符合其最近五个元素的规格!所以你真的希望它被'同步',以便这是一个原子操作。尽管如此,即使在同步时,仍然需要在删除之前添加,因为如果删除然后添加失败,则无法退出。 – 2014-09-06 07:14:10

1

Size-limited queue that holds last N elements in Java


阿帕奇百科全书集合4具有CircularFifoQueue这是你在找什么。 引述的Javadoc:

CircularFifoQueue是先入先出队列的具有固定大小,如果充分,取代它的最旧的元件。

如果您使用的是Apache Commons Collections中(3.X)的旧版本,你可以使用CircularFifoBuffer这基本上是没有泛型同样的事情。

更新:更新回答以下的公共收藏版发布4

0

什么我不知道该怎么做的就是这样的ArrayList的“微调”本身。一些指导将非常感谢。

How to design a Least Recently Used (LRU) Cache in Java。但它不使用ArrayList

import java.util.concurrent.ConcurrentHashMap; 
import java.util.concurrent.ConcurrentLinkedQueue; 

public class LRUCache<K, V> { 

    //Maximum capacity for the LRU cache. 
    private final int capacity; 
    //Queue to store the recently used keys. 
    private ConcurrentLinkedQueue<K> queue; 
    //Key-Value store to maintain the actual object. 
    private ConcurrentHashMap<K, V> map; 

    /** 
    * Initial capacity for the LRU Cache. 
    * @param capacity 
    */ 
    public LRUCache(final int capacity) { 
     this.capacity = capacity; 
     this.queue = new ConcurrentLinkedQueue<K>(); 
     this.map = new ConcurrentHashMap<K, V>(capacity); 
    } 

    /** 
    * Check whether the items exists in the cache. Returns null if key doesn't exists in the cache. 
    * @param key 
    * @return 
    */ 
    public V get(final K key) { 
     return map.get(key); 
    } 

    /** 
    * Add new value to the LRU Cache. If the key already exists, 
    * the key will be promoted to the front of the cache. 
    * Neither the key nor the value can be null. 
    * @param key 
    * @param value 
    * @throws NullPointerException 
    */ 
    public synchronized void put(final K key, final V value) { 
     if(key == null || value == null) { 
      throw new NullPointerException(); 
     } 
     if (map.containsKey(key)) { 
      queue.remove(key); 
     } 
     while (queue.size() >= capacity) { 
      K expiredKey = queue.poll(); 
      if (expiredKey != null) { 
       map.remove(expiredKey); 
      } 
     } 
     queue.add(key); 
     map.put(key, value); 
    } 
} 

您也可以使用LinkedHashMap。但是,它不是ArrayList。请参阅Pro Android Apps Performance Optimization。第1章“优化Java代码”;关于“缓存结果”部分和LruCache<K, V>;和第4章“高效使用内存”。

相关问题