2014-09-06 51 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章「高效使用內存」。

相關問題