如何在java中创建固定大小的通用缓冲区?

时间:2011-02-06 06:57:47

标签: java generics

如果我想创建一个固定大小的整数缓冲区,我会使用new int[size]。现在,假设我想在泛型类型上创建一个缓冲区。

一个可能的解决方案是:

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。请注意,这不是真实的用例,而是面试问题。

4 个答案:

答案 0 :(得分:3)

你可以做这样的事情

private final T[] items;

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

你必须转发T[],但它确实是T[]而不是Object[]

答案 1 :(得分:1)

由于Java中的泛型系统已断开,您无法使用参数化数组定义,但由于类型擦除,您可以选择将一个对象数组分配给参数数组声明,然后它可以绕过VM的类型系统在运行时。 在此之后,使用此数组的任何操作都必须满足类型T,编译器将确保在编译时发生。你只需要解决这个定义。

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

Java theory and practice: Generics gotchas

答案 2 :(得分: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);
   }

}

** 编辑 **

或者更具体地说,创建自己的Collection兼容泛型类。例如:

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;
   }
}

此未经测试的类将允许getset以及remove操作,但不允许add等。但如果您愿意,可以根据自己的规范实施。如果您需要添加一个功能(例如ensureCapacity)来实现它而不涉及任何其他来源,那么实现类而不是使用固定大小的数组将允许您。

** 更新 **

我刚刚看到你的编辑,基本上,你正在开始。只需使用一个Object数组,当你得到一个元素时,你将其转换为你的泛型类型。例如,请参阅Java的ArrayList实现。

答案 3 :(得分:0)

您正在寻找

java.util.ArrayDeque(或java.util.concurrent.ArrayBlockingQueue)。但是,我建议你实现自己的循环缓冲区/队列。这是一个非常好的练习。

至于缓存int []我建议你不要这样做。 重要提示:如果要使用某些缓存机制,请不要像tomcat那样使用ConcurrentLinkedQueue。 缓存应该使用堆栈而不是队列,ArrayDeque和ArrayBlockingQueue都适合堆栈。