简体   繁体   English

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

[英]Which Java collection type should I use?

I'm trying to create a "Limited List" in Java. 我正在尝试在Java中创建“受限列表”。 It should remove old entries if I add new entries. 如果我添加新条目,它将删除旧条目。

eg If the list size is 3, and I add the 4rd item, it should remove the 1st item. 例如,如果列表大小为3,并且我添加了第4个项目,则应该删除第一个项目。 Currently I solved this using remove(0) in a ArrayList , but I heard ArrayList s are very slow. 目前,我在ArrayList使用remove(0)解决了此问题,但我听说ArrayList的速度非常慢。

Is there a faster way to solve this? 有没有更快的方法来解决这个问题? My current code is: 我当前的代码是:

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;
    }

}

but I heard ArrayList's are very slow. 但是我听说ArrayList的速度很慢。

Some operations are slow for ArrayList s others for other collections. 对于ArrayList 某些操作很慢,而对于其他集合, 某些操作则很慢。 This is because an ArrayList uses an array behind the curtains, and for a remove operation in the head, it has to shift all the elements one to the left. 这是因为ArrayList在窗帘后面使用了一个数组,并且为了在头部执行删除操作,它必须将所有元素向左移动。 Therefore in terms of big oh, removing from the head is O(n) for ArrayList s where it is O(1) for LinkedList s. 因此,就大哦而言,从头移除是ArrayListO(n) ,而从LinkedList的头是O(1)

If you only want to add items in the tail of the collection and remove elements in the head, I propose you use a LinkedList : 如果您只想在集合的末尾添加项目,并在头部删除元素,那么我建议您使用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;
    }

}

An important note from @JBNizet is that you should inherit from ArrayList or LinkedList directly, but implement a Collection<T> , something like: @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...

}

Please: don't give a nickel on "what you hear". 请:不要在“您听到的内容”上多说几句。 Programming is about hard facts, not hearsay. 编程是关于硬事实,而不是传闻。 You can be very sure that all the collection implementations were written by experts in the field; 您可以确定所有收集实现都是由该领域的专家编写的; so the first thing would be to check the various documentation out there to assess if the operations that you need really come with a significant performance tag to you. 因此,第一件事是查看那里的各种文档,以评估您所需的操作是否确实带有显着的性能标签 Yes, collection operations have different cost, but all of that is documented. 是的,收集操作具有不同的成本,但是所有这些都已记录在案。

Then: if you are really only talking about 3, 4 elements ... do you really really think that performance matters? 然后:如果您真的只在谈论3、4个要素……您真的真的认为绩效很重要吗? That would only be the case if you would be using this lists for (hundreds of) thousands of times per minute or so. 仅当您将此列表每分钟(数千次)数千次使用时才是这种情况。 Keep in mind what a modern CPU can do in a few micro seconds nowadays; 请记住,当今的现代CPU在几微秒内能做什么? and how many method calls you need to have in order for "call B is 5 nanoseconds slower" to be noticeable. 以及需要多少次方法调用才能使“调用B慢5纳秒”。

In other words: strive for good, clean (SOLID based) designs; 换句话说:争取良好,干净(基于SOLID的)设计; instead of worrying about potential performance problems. 而不用担心潜在的性能问题。 That will pay off 10 times more compared to spending hours on topics like this. 与在此类主题上花费数小时相比,这将带来10倍的回报。

You see: one should be really careful about "performance issues". 您会看到:应该对“性能问题”非常小心。 Because: you only realize that you have one ... when there are complains from your users. 因为:当用户提出投诉时,您才意识到自己只有一个...。 And if that happens, you don't start blindly by trying to improve this or that; 而且,如果发生这种情况,您就不会盲目地尝试改善这一点; no then you first do profiling to measure where your problems are coming from. 不,那么您首先要进行性能分析以衡量问题的根源。 And then you fix those things that need improvement. 然后您修复那些需要改进的东西。

EDIT: so your last comment indicates that you did some sort of measurement (hint: if you would have said so directly, instead of writing "I heard that lists are slow" ... probably you would have gotten a different answers already). 编辑:所以您的最后一条评论表明您进行了某种衡量(提示:如果您直接这么说,而不是写“我听说列表很慢”……可能您已经得到了不同的答案)。 OK, lets assume that you did good profiling (where: even when one collection types performs slower for you, the question is still: will it be called so often to cause trouble). 好的,假设您进行了良好的性能分析(其中:即使一种收集类型对您而言执行速度较慢,问题仍然是:它会经常被调用而引起麻烦)。 Anyway: what you really ant to is to understand access patterns that you do on your code. 无论如何:您真正想要做的是了解您对代码执行的访问模式 Do you need random access, do you iterate in lists, etc. You see, typically, a container that forgets elements ... that sounds more like a cache than a list. 您是否需要随机访问,是否在列表中进行迭代等等?通常您会看到一个容器,该容器会遗忘元素……听起来更像是一个缓存,而不是列表。 In that sense: do you rely on quick in-sequence retrieval of objects; 从这个意义上说:您是否依赖于对象的快速顺序检索? or how is data accessed? 或如何访问数据? Those are the questions that you have to ask yourself; 这些是您必须问自己的问题; and only then you can decide if you should implement your own special limited list; 只有这样,您才能决定是否应该实施自己的特殊限制列表; or if there are existing components (maybe from apache commons or guava) that give you what you need. 或者是否有现有组件(可能来自apache commons或番石榴)满足您的需求。

I think you should use Queues, because this kind of collection use a FIFO procedure (First In - First Out). 我认为您应该使用队列,因为这种收集使用FIFO过程(先进先出)。 So the first element you inserted will be the first that goes out and you can manage simply your queue by using methods like Enqueue and Dequeue (both runs in O(1)). 因此,您插入的第一个元素将是第一个出现的元素,您可以使用Enqueue和Dequeue(均在O(1)中运行)之类的方法来简单地管理队列。

If you are fine with writing code, best option would be not to extend any existing collection and make your own collection. 如果您擅长编写代码,最好的选择是不要扩展任何现有集合并创建自己的集合。 For list, you can implement list interface.( recommended approach is to take AbstractList abstract class) 对于列表,可以实现列表接口。(推荐的方法是采用AbstractList抽象类)

This will give you more control and you can design for speed. 这将为您提供更多控制权,并且可以设计速度。

Fastest option would be to dump the collection and simply use a array (wrap operation in a class). 最快的选择是转储集合并仅使用数组(类中的包装操作)。 However, that may not be suitable for you as it will not be under collection hierarchy. 但是,这可能不适合您,因为它不在集合层次结构中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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