2011-02-06 80 views
1

如果我想創建一個固定大小的整數緩衝區,我會使用new int[size]。現在,假設我想創建一個通用類型的緩衝區。如何在java中創建一個固定大小的通用緩衝區?

一個可能的解決方案是:

List<T> buffer = new ArrayList<T>(size); 
for (int i = 0; i < size; ++i) 
    buffer.add(null); 

// now simply access the buffer via buffer.get() and buffer.set() 

是否有更好的東西,我應該使用?示例用例爲implement a queue。請注意,這不是一個真實的用例,而是一個面試問題。

+0

嗯,你究竟想要做什麼? – Falmarri 2011-02-06 07:00:19

+0

@Falmarri - 我試圖實現一個循環隊列,並希望使用「緩衝」結構作爲基礎數據存儲。我需要能夠分配一個固定大小的緩衝區,並通過索引訪問元素。 – ripper234 2011-02-06 07:05:43

+0

但是,爲什麼你需要一個緩衝區,可以容納你不知道在編譯時的任意對象? – Falmarri 2011-02-06 07:07:11

回答

0

只需將一個通用集合包裝在自定義類中,即可以控制固定大小的集合。例如:

class Queue<T> { 
    private ArrayList<T> q; 
    private int size; 

    public Queue(int size) { 
     this.size = size; 
     this.q = new ArrayList<T>(size); 
    } 

    public int size() { 
     return size; 
    } 

    // ... 

    public T get(int index) { 
     if (index > q.size()) { 
      return null; 
     } 
     // ... or whatever 

     return q.get(index); 
    } 

} 

** 編輯 **

或者更具體地說,建立自己的最愛兼容的通用類。例如:

public class FixedQueue<E> extends AbstractList<E> { 

    private Object[] queue; 

    public FixedQueue(int size) { 
     queue = new Object[size]; 
    } 

    @Override 
    public E set(int index, E element) { 
     Object old = queue[index]; 
     queue[index] = element; 
     modCount++; 
     return (E) old; 
    } 

    @Override 
    public E get(int index) { 
     return (E) queue[index]; 
    } 

    @Override 
    public int size() { 
     return queue.length; 
    } 

    @Override 
    public E remove(int index) { 
     Object old = queue[index]; 
     System.arraycopy(queue, index+1, queue, index, queue.length - index - 1); 
     modCount++; 
     return (E) old; 
    } 
} 

這個未經測試的類將允許getsetremove操作,但不add等,但你可以實現它自己的規格,如果你想。如果您需要添加功能(例如ensureCapacity)來實現它,而不觸及任何其他源,則實現一個類而不是使用固定大小的數組將允許您執行此操作。

** UPDATE **

我剛纔看到您的編輯,基本上,你開始出發吧。只需使用一組Object,當你獲得一個元素時,該數組就會轉換爲泛型類型。例如,請參閱Java的ArrayList實現。

1

由於Java中泛型系統的破壞,您不能使用參數化數組定義,但由於類型擦除,您可以知道或者可以將一個對象數組分配給參數化數組聲明,然後它可以繞過運行時虛擬機的類型系統。 之後,這個數組的任何操作都必須滿足T類型,編譯器會確保在編譯時發生。你只需要解決這個定義。

class ArrayList<V> { 
    private V[] backingArray; 
    public ArrayList() { 
    backingArray = (V[]) new Object[DEFAULT_SIZE]; 
    } 
} 

Java theory and practice: Generics gotchas

3

你可以做這樣的事情

private final T[] items; 

public RingBuffer(Class<T> clazz, int capacity) { 
    this.items = (T[]) Array.newInstance(clazz, capacity); 
} 

你必須轉換爲T[],但它確實是一個T[]而不是Object[]

0

java.util.ArrayDeque(或Java。 util.concurrent.ArrayBlockingQueue)是你在找什麼。但是,我建議你實現自己的循環緩衝區/隊列。這是一個非常好的練習。

至於緩存int []我建議你不要這樣做。 重要說明:如果你想使用一些緩存機制,不要像tomcat那樣做並使用ConcurrentLinkedQueue。 緩存應該使用堆棧不是隊列,ArrayDeque和ArrayBlockingQueue都適用於堆棧。