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

时间:2016-06-18 12:19:14

标签: java collections

我试图创建一个"有限列表"在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;
    }

}

4 个答案:

答案 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的重要提示是,您应该直接从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...

}

答案 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抽象类)

这将为您提供更多控制,您可以设计速度。

最快的选择是转储集合并简单地使用数组(在类中进行换行操作)。但是,这可能不适合您,因为它不会在集合层次结构下。