2011-02-06 34 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都适用于堆栈。

相关问题