3

我想在 java 中创建一个列表,在添加新元素时,将检查是否达到限制。如果是,请删除最旧的元素。

我正在考虑制作 ArrayList 的子级并覆盖 add(Object)。在那里我会这样做:

if(size() + 1 > MAX)
    remove(get(0));
super.add(newObject);

有更好的办法吗?

4

6 回答 6

5

对此可能有多种解决方案,但我认为如果您进行一次更改,您的方法是一种合适的方法:您的底层实现类应该是 a LinkedList,而不是ArrayList. 原因是当您在删除的值之后调用remove每个ArrayList元素时,必须向上移动(这remove(0)是最坏的情况!)。但是,这对于LinkedList.

于 2013-09-23T11:50:55.530 回答
1

你描述的是一个循环先进先出缓冲区。您可以使用 Apache Commons-collections 实现。

有关文档,请参阅Commons CollectionsCircularFifoBuffer

于 2013-09-23T12:02:29.457 回答
0

您可以按照您描述的方式进行操作,但这样的列表的性能会很低。想象一下已经达到了限制,并且您删除了第一个元素。在幕后,这将涉及将底层数组的所有元素向上复制一个索引。然后将新元素添加到最后一个索引。尤其是所有元素的复制成本很高

或者,您可以使用 a LinkedList,这对于此类操作更有效。

另一种方法是编写自己的类来实现Circular Buffer。这基本上是一个大小为 MAX 的数组。您必须保留第一个元素的索引和数组中的元素数。添加元素时,检查元素的数量是否等于 MAX,如果是,则覆盖第一个元素并将第一个元素的索引增加一。索引的 getter 和 setter 也需要考虑第一个元素的偏移量,但这并不过分复杂。

最佳选择取决于您的用例。如果您必须在列表中的随机位置进行大量插入和删除,LinkedList绝对是要走的路。如果只想将项目添加到末尾并移除头部,则循环缓冲区非常有效。

于 2013-09-23T11:56:01.223 回答
0

IMO,您应该使用带有列表包装器的数组。然后你可以做任何你想做的事情。您还可以添加返回列表的方法,例如 get。

于 2013-09-23T11:56:46.243 回答
0

您可以使用Deque

private final int LIMIT = 10;

private Deque<String> queue = new ArrayDeque<String>(LIMIT);

public void addToList(final String element) {
   Deque<String> queue = new ArrayDeque<String>(LIMIT);
   if (!queue.offer(element)) {
      queue.removeFirst();
      queue.offer(element);
   }
}
于 2013-09-23T11:59:29.520 回答
0

创建自己的类来完成这项工作。跟踪两个变量。一个表示零元素,一个表示下一个元素的位置。

public class MyList<T>
{
    private T array[];
    private int first;
    private int next;
    private int count;

    public MyList(int count)
    {
        array = new T[count];
    }

    public void add(T obj)
    {
        array[next++] = obj;
        next %= array.length;
        if (count == array.length)
        {
            zero = (zero + 1) % array.length;
        } else count++;
    }

    public T get(int index)
    {
        return array[(zero + index) % array.length];
    }
}
于 2013-09-23T12:16:05.893 回答