Java集合框架中队列类在哪里?

26

我只看到了一个队列接口,Java集合框架中没有队列类吗?

9个回答

37

13
不知道为什么人们不去看JavaDocs :P +1 - Perpetualcoder
7
对于那些真的很懒的人,我要说明一下,所有带有DeQue的都是双向队列。 - Powerlord
2
我有些困惑。我只想要一个FIFO数据结构,让我像维基百科上展示的那样入队和出队项目,而不需要任何专业的东西。我该选择哪一个?难道Java没有类似于C++ STL队列的等效物吗? - Pieter
4
@Pieter: 这些类中的任何一个都能执行基本的进队和出队操作。如果您愿意,您可以声明您的队列为一个Queue,例如 Queue<MyObject> myQueue = new LinkedList<MyObject>(),这将强制您遵循在接口中声明的队列操作(例如add/remove)。 - Michael Myers

10

队列有多种实现方式:根据API文档:

所有已知的实现类:

AbstractQueue, ArrayBlockingQueue, ArrayDeque, ConcurrentLinkedQueue, 
DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedList, 
PriorityBlockingQueue, PriorityQueue, SynchronousQueue

注意,AbstractQueue不是一个具体的类。

其中一些来自concurrent包,因此如果你正在实现一个作业队列或类似的东西,你应该选择ConcurrentLinkedQueue或PriorityBlockingQueue(对于堆)。


7

根据http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html的说明,ArrayList没有实现Queue。 - James McMahon
是的,当我回去获取一些链接时,我意识到了这一点;显然我的记忆有误。 - Rob
4
没问题。如果你已经把整个Java库都背下来了,我会感到印象深刻。但如果你还连EE也都记住了,我会慢慢后退的。 - James McMahon
2
嗯,有javax.activation、javax.annotation、javax.ejb,等等...等等,等等,你要去哪里?还有很多呢!;) - Rob

4
    Queue<Integer> queue = new ArrayDeque<>();

    queue.add(1);
    queue.add(2);
    queue.add(3);

    while (!queue.isEmpty()) {
        System.out.println(queue.remove());// prints 1 2 3
    }

您也可以使用LinkedList。但是通常,对于Queue,ArrayDeque优于LinkedList。因为ArrayDeque消耗较少的内存,速度更快,并且不允许null。不允许null很好,因为如果允许null,在执行peek()或poll()时,即使队列不为空,您也可能会得到null。


3
不,没有 Queue 类,因为有很多不同的方法可以实现队列,你必须选择适合你使用情况的方法。与集合框架中的任何其他集合一样,例如,ArrayListLinkedList 都实现了一个 List。通常模式(这是对象继承的良好用法)是:
- 接口,例如 Queue,定义了你想让对象扮演的角色; - 子接口,例如 Deque,进一步扩展或专业化角色 - 在这种情况下,“deque” 或双端队列允许您从队列的两端添加和删除元素,而不仅仅是从后面添加并从前面删除; - 提供了如何执行对象的角色的实现。例如,ArrayDeque 使用可调整大小的数组来实现双端队列,它具有不同的优缺点,与使用链表的 LinkedList 不同。
为了阐述接口作为角色的概念,请注意,即使 ArrayDeque 实现了 Deque,您也可以将其用作 Queue,而无需担心,因为实现两个接口意味着它可以扮演两个角色。同样,LinkedList 可以戴上列表、队列或双端队列的帽子。
出于这个原因,使用类似于集合框架的东西的正常(推荐)方法是,按照接口编程,也就是在使用类时使用接口而不是类名本身。例如,您可以像这样实例化一个对象:
Queue<String> logQueue = new ConcurrentLinkedQueue<String>();
...
logQueue.add("Log message");

通过这种方式,您不会被绑定到特定的类中,如果需要替换,也不需要修改太多代码,

  • 并且通过为类命名其所扮演的角色来记录您正在做什么。这有助于实现 自我记录代码 的一般原则,即让代码本身自我说明而无需使用注释等。

3
除了使用API文档查找“所有已知的实现类”外,通常还有其他非公共实现可通过公共API获得(只需少量无意义的文档即可)。如果单击“use”,您还将找到Collections.asLifoQueueDeque已经是Queue,但它是FIFO而不是堆栈)。

时不时地,我会重新发现“使用”页面并想:“嘿,这太棒了!”然后我又会忘记它们。 - Michael Myers
“使用”页面的用户界面不是最好的。 - Tom Hawtin - tackline

2

2
尽管答案听起来有点傲慢,但他们实际上非常酷地教你如何钓鱼。队列仅是查看集合的方法,因此许多集合可能会实现它。同时,像线程队列这样具有特定其他逻辑的东西可能使用相同的接口。
知道在javadocs中查找哪里是很大的帮助。我相信你已经找过了,只是没有想到要查看实现。人生就是不断学习。
有时,您还需要追踪子类/扩展列表。例如,如果您查看队列并看到AbstractQueue,则可能想查看实现该类的类。
我会帮你去掉一个-1 :)

0
import java.util.Queue;

就是这样

Enqueue function == Queue_Object.add(input_value);

Dequeue function == Queue_Object.pull();   //return the value and delete it from queue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接