繁体   English   中英

我应该使用哪种Java集合类型?

[英]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在窗帘后面使用了一个数组,并且为了在头部执行删除操作,它必须将所有元素向左移动。 因此,就大哦而言,从头移除是ArrayListO(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的一个重要说明是,您应该直接从ArrayListLinkedList继承,但是要实现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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM