我试图创建一个"有限列表"在Java中。如果我添加新条目,它应该删除旧条目。
e.g。如果列表大小为3,并且我添加了第4项,则应删除第1项。目前我在remove(0)
中使用ArrayList
解决了这个问题,但我听说ArrayList
非常慢。
有更快的方法来解决这个问题吗?我目前的代码是:
public class LimitedList<T> extends ArrayList<T> {
private int maximum;
public LimitedList(int maximum) {
this.maximum = maximum;
}
@Override
public boolean add(T t) {
boolean r = super.add(t);
while (size() > maximum) {
remove(0);
}
return r;
}
}
答案 0 :(得分:6)
但我听说ArrayList非常慢。
某些操作对于其他集合的ArrayList
其他操作来说很慢。这是因为ArrayList
使用窗帘后面的数组,并且对于头部中的移除操作,它必须将所有元素向左移动一个。因此,就大的问题而言,从ArrayList
开始移除 O(n),LinkedList
的 O(1)第
如果您只想在集合的尾部添加项目并删除头部中的元素,我建议您使用LinkedList
:
public class LimitedList<T> extends LinkedList<T> {
private int maximum;
public LimitedList(int maximum) {
this.maximum = maximum;
}
@Override
public boolean add(T t) {
boolean r = super.add(t);
int n = this.size();
while (n > maximum) {
this.removeFirst();
n--;
}
return r;
}
}
来自@JBNizet的重要提示是,您应该直接从ArrayList
或LinkedList
继承,但要实施Collection<T>
,例如:
public class LimitedList<T> implements Collection<T> {
private final LinkedList<T> list;
private int maximum;
public LimitedList(int maximum) {
this.list = new LinkedList<T>();
this.maximum = maximum;
}
@Override
public boolean add(T t) {
boolean r = this.list.add(t);
int n = this.list.size();
while (n > maximum) {
this.list.removeFirst();
n--;
}
return r;
}
//implement other Collection methods...
}
答案 1 :(得分:2)
请:不要对“听到的内容”给出任何评价。编程是关于事实,而不是道听途说。您可以非常肯定所有的集合实现都是由该领域的专家编写的;因此,首先要检查那里的各种文档,以评估您所需的操作是否真的带有重要性能标记。 是的,收集操作有不同的成本,但所有这些都记录在案。
然后:如果你真的只谈论3,4个元素......你真的认为性能很重要吗?只有在每分钟左右(数百)次使用此列表的情况下才会出现这种情况。请记住现代CPU在几微秒内可以做到的事情;以及“呼叫B慢5纳秒”需要多少方法调用才能引人注目。
换句话说:追求良好,干净(基于SOLID)的设计;而不是担心潜在的性能问题。与在这样的话题上花费数小时相比,这将获得10倍的回报。
你看:人们应该非常小心“性能问题”。因为:当您的用户抱怨时,您只会意识到您有一个......如果发生这种情况,你不要盲目地尝试改善这个或那个;不,那么你先做分析来衡量问题的来源。 然后你解决那些需要改进的事情。
编辑:所以你的最后评论表明你做了某种测量(提示:如果你直接这么说,而不是写“我听说列表很慢”......可能你会得到一个不同的答案已经)。好吧,我们假设你做了很好的分析(其中:即使一个集合类型对你来说执行速度较慢,问题仍然是:它会经常被调用以引起麻烦)。无论如何:你真正想要的是理解你对代码所做的访问模式。你需要随机访问,你是否在列表中进行迭代等等。你通常会看到一个忘记元素的容器......听起来更像是缓存而不是列表。从这个意义上讲:你是否依赖快速按顺序检索对象;或者如何访问数据?这些是你必须问自己的问题;只有这样你才能决定是否应该实施自己的特殊限制清单;或者如果有现有的组件(可能来自apache commons或guava)可以满足您的需求。
答案 2 :(得分:1)
我认为你应该使用Queues,因为这种集合使用FIFO程序(First In-First Out)。因此,您插入的第一个元素将是第一个出去的元素,您可以使用Enqueue和Dequeue等方法管理您的队列(两者都在O(1)中运行)。
答案 3 :(得分:1)
如果您可以编写代码,最好的选择是不扩展任何现有的集合并制作您自己的集合。对于列表,您可以实现列表界面。(推荐的方法是采用AbstractList抽象类)
这将为您提供更多控制,您可以设计速度。
最快的选择是转储集合并简单地使用数组(在类中进行换行操作)。但是,这可能不适合您,因为它不会在集合层次结构下。