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