[英]Which Java collection type should I use?
我正在尝试在Java中创建“受限列表”。 如果我添加新条目,它将删除旧条目。
例如,如果列表大小为3,并且我添加了第4个项目,则应该删除第一个项目。 目前,我在ArrayList
使用remove(0)
解决了此问题,但我听说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;
}
}
但是我听说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...
}
请:不要在“您听到的内容”上多说几句。 编程是关于硬事实,而不是传闻。 您可以确定所有收集实现都是由该领域的专家编写的; 因此,第一件事是查看那里的各种文档,以评估您所需的操作是否确实带有显着的性能标签 。 是的,收集操作具有不同的成本,但是所有这些都已记录在案。
然后:如果您真的只在谈论3、4个要素……您真的真的认为绩效很重要吗? 仅当您将此列表每分钟(数千次)数千次使用时才是这种情况。 请记住,当今的现代CPU在几微秒内能做什么? 以及需要多少次方法调用才能使“调用B慢5纳秒”。
换句话说:争取良好,干净(基于SOLID的)设计; 而不用担心潜在的性能问题。 与在此类主题上花费数小时相比,这将带来10倍的回报。
您会看到:应该对“性能问题”非常小心。 因为:当用户提出投诉时,您才意识到自己只有一个...。 而且,如果发生这种情况,您就不会盲目地尝试改善这一点; 不,那么您首先要进行性能分析以衡量问题的根源。 然后您修复那些需要改进的东西。
编辑:所以您的最后一条评论表明您进行了某种衡量(提示:如果您直接这么说,而不是写“我听说列表很慢”……可能您已经得到了不同的答案)。 好的,假设您进行了良好的性能分析(其中:即使一种收集类型对您而言执行速度较慢,问题仍然是:它会经常被调用而引起麻烦)。 无论如何:您真正想要做的是了解您对代码执行的访问模式 。 您是否需要随机访问,是否在列表中进行迭代等等?通常您会看到一个容器,该容器会遗忘元素……听起来更像是一个缓存,而不是列表。 从这个意义上说:您是否依赖于对象的快速顺序检索? 或如何访问数据? 这些是您必须问自己的问题; 只有这样,您才能决定是否应该实施自己的特殊限制列表; 或者是否有现有组件(可能来自apache commons或番石榴)满足您的需求。
我认为您应该使用队列,因为这种收集使用FIFO过程(先进先出)。 因此,您插入的第一个元素将是第一个出现的元素,您可以使用Enqueue和Dequeue(均在O(1)中运行)之类的方法来简单地管理队列。
如果您擅长编写代码,最好的选择是不要扩展任何现有集合并创建自己的集合。 对于列表,可以实现列表接口。(推荐的方法是采用AbstractList抽象类)
这将为您提供更多控制权,并且可以设计速度。
最快的选择是转储集合并仅使用数组(类中的包装操作)。 但是,这可能不适合您,因为它不在集合层次结构中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.