我想在 java 中创建一个列表,在添加新元素时,将检查是否达到限制。如果是,请删除最旧的元素。
我正在考虑制作 ArrayList 的子级并覆盖 add(Object)。在那里我会这样做:
if(size() + 1 > MAX)
remove(get(0));
super.add(newObject);
有更好的办法吗?
对此可能有多种解决方案,但我认为如果您进行一次更改,您的方法是一种合适的方法:您的底层实现类应该是 a LinkedList
,而不是ArrayList
. 原因是当您在删除的值之后调用remove
每个ArrayList
元素时,必须向上移动(这remove(0)
是最坏的情况!)。但是,这对于LinkedList
.
你描述的是一个循环先进先出缓冲区。您可以使用 Apache Commons-collections 实现。
您可以按照您描述的方式进行操作,但这样的列表的性能会很低。想象一下已经达到了限制,并且您删除了第一个元素。在幕后,这将涉及将底层数组的所有元素向上复制一个索引。然后将新元素添加到最后一个索引。尤其是所有元素的复制成本很高
或者,您可以使用 a LinkedList
,这对于此类操作更有效。
另一种方法是编写自己的类来实现Circular Buffer。这基本上是一个大小为 MAX 的数组。您必须保留第一个元素的索引和数组中的元素数。添加元素时,检查元素的数量是否等于 MAX,如果是,则覆盖第一个元素并将第一个元素的索引增加一。索引的 getter 和 setter 也需要考虑第一个元素的偏移量,但这并不过分复杂。
最佳选择取决于您的用例。如果您必须在列表中的随机位置进行大量插入和删除,LinkedList
绝对是要走的路。如果只想将项目添加到末尾并移除头部,则循环缓冲区非常有效。
IMO,您应该使用带有列表包装器的数组。然后你可以做任何你想做的事情。您还可以添加返回列表的方法,例如 get。
您可以使用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);
}
}
创建自己的类来完成这项工作。跟踪两个变量。一个表示零元素,一个表示下一个元素的位置。
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];
}
}