实现Queue 和 Qeque 接口的类
类 | 描述 |
---|---|
AbstractDueue | 此类提供某些 Queue 方法的骨干实现,为其它类集合的实现提供方便 |
PriorityQueue | 一个基于优先级堆的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法 |
ArrayDeque | 双端队列的一个数组实现, 数组双端队列没有容量限制;它们可根据需要增加以支持使用 |
LinkedLis | 通过继承 AbstractSequentialList 来实现链接列表 |
LinkedList 类实现了接口 Queue 和 Deque, 具备了操作队列的基本方法。通常可以作为队列 和 双向队列的实现类使用,也是用得比较普遍的队列数据结构。
一个基于优先级堆的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法。 优先级队列不允许使用 null 元素。依靠自然顺序的优先级队列还不允许插入不可比较的对象。
此队列的“头”是按指定排序方式确定的最小元素。如果多个元素都是最小值,则头是其中一个元素 ——— 选择方法是任意的。队列获取操作 poll, remove, peek 和 element 访问处于队列头的元素。
优先级队列是无界的,但是有一个内部容量, 控制着用于存储队列元素的数组大小。它通常至少等于队列的大小。随着不断向优先级队列添加元素,其容量会自动增加。无须指定容量增加策略的细节。
此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选方法。方法 iterator()中提供的迭代器不保证以任何特定的顺序遍历优先级队列中的元素。
此实现为排队和出队方法 (offer,poll, remove() 和add() 提供)O(long(n))时间,为 remove( Object) 和 contains( Object) 方法提供线性时间,为 获取方法(peek,element,和size)提供固定时间。
PriorityQueue 提供了如下 6 个构造函数。
// 使用默认的初始容量(11)创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。
public PriorityQueue();
// 使用指定的初始容量创建一个 PriorityQueue 并根据其自然顺序对元素进行排序
public PriorityQueue(int initialCapacity);
// 使用指定的初始容量创建一个 PriorityQueue ,并根据指定的比较器对元素进行排序
public PriorityQueue(int initialCapacity, Comparator super E> comparator);
// 创建包含指定 collection 中的元素的 PriorityQueue 。
// 如果指定的 collection 是 SortedSet 的一个实例
// 或者是另一个 PriorityQueue 那么此优先级队列将根据相同顺序进行排序。
// 否则,此优先级队列将根据元素的自然顺序进行排序。
public PriorityQueue(Collection extends E> c);
// 创建包含指定优先级队列元素的 PriorityQueue。 此优先级队列将根据与给定优先级队列相同的顺序进行排序。
public PriorityQueue(PriorityQueue extends E) c);
// 创建包含指定有序 set 元素的 PriorityQueue。此优先级队列将根据与给定有序 set 相同的顺序进行排序。
public PriorityQueue(SortedSet extends E> c);
PriorityQueue使用
import java.util.*;
public class QueueDemo {
public static void main(String[] args) {
PriorityQueue pq = new PriorityQueue();
// 队列中的元素按照自然顺序排序,元素加入的顺序与元素在队列中的顺序无关
pq.add("D");
pq.add("E");
pq.add("F");
pq.add("A");
pq.add("B");
pq.add("C");
// 输出队列中的元素,不保证以任何特定的顺序遍历优先级队列中的元素。
// toString方法中使用了迭代器。
System.out.println("队列中的元素:" + pq.toString());
System.out.println("队列中的第一个元素:" + pq.peek());
System.out.println("移除队列中的元素:" + pq.remove());
System.out.println("队列中的元素:" + pq.toString());
System.out.println("移除队列中的元素:" + pq.poll());
System.out.println("队列中的元素:" + pq.toString());
}
}
// 队列中的元素:[A, B, C, E, D, F]
// 队列中的第一个元素:A
// 移除队列中的元素:A
// 队列中的元素:[B, D, C, E, F]
// 移除队列中的元素:B
// 队列中的元素:[C, D, F, E]
是 Deque 接口的大小可变数组的实现。数组双端容量没有限制;它们可根据需要增加以支持使用。它们不是现场安全的;在没有外部同步时,它们不支持多个线程的并发方法,禁止 null 元素。此类很可能在用作堆栈时快于 Stack, 在用作队列时快于 LinkendList 。
大多数 ArrayDeque 操作可以摊销固定时间运行。异常包括 remove,removeFirstOccurrence, removeLastOccurrence, Contains, iterator,.remove() 以及批量操作,它们均以线性时间允许。
此类的 iterator 方法返回的迭代器是快速失败的:如果在创建迭代器后的任意时间通过除迭代器本身的 remove 方法之外的任何其他方式修改了双端队列,则迭代器通常将抛出 ConcurrrentModificationException.因此,面对并发修改,迭代器很快就会完全失败,而不是冒着在将来不确定的时刻任意发生不确定行为的风险。
注意: 迭代器的快速失败行为不能得到保证。一般来说,存在不同步的并发修改时,不可能做出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException 。以此,编写依赖于此异常的程序是错误的,
正确的做法是:迭代器的快速失败行为应该仅用于检测错误(bug)。
ArrayDeque提供了如下 3 个构造函数:
//构造一个初始容量能够容纳16 个元素的空数组双端队列
public ArrayDeque();
//构造一个初始容量能够容纳指定数量的元素的空数组双端队列
public ArrayDeque(int numElements);
//构造一个包含指定 collection 的元素的双端队列,这些元素按 collection 的迭代器返回的顺序排序 (collection 迭代器返回的第一个元素将是第一个元素,或双端队列的开头)
public ArrayDeque(Collection extends E> c);
ArrayDeque的使用
import java.util.*;
public class QueueDemo {
public static void main(String[] args) {
ArrayDeque ad = new ArrayDeque();
ad.add("D");
ad.offerFirst("E");
ad.addFirst("F");
ad.offer("A");
ad.addLast("B");
ad.offerLast("C");
System.out.println("队列中的元素:" + ad.toString());
System.out.println("队列中的第一个元素:" + ad.peekFirst());
System.out.println("移除队列中的元素:" + ad.remove());
System.out.println("队列中的元素:" + ad.toString());
System.out.println("移除队列中的元素:" + ad.pollLast());
System.out.println("队列中的元素:" + ad.toString());
}
}
// 队列中的元素:[A, B, C, E, D, F]
// 队列中的第一个元素:A
// 移除队列中的元素:A
// 队列中的元素:[B, D, C, E, F]
// 移除队列中的元素:B
// 队列中的元素:[C, D, F, E]