Java中的BlockingDeque
BlockingDeque接口是Java集合框架的一部分。它之所以得名,是因为它阻止了非法操作,例如插入到满队列或从空队列中删除,所有这些属性都内置在这个接口的结构中。由于是deque(双端队列),所以插入、删除、遍历操作都可以从两端进行。 BlockingDeque 是一个接口,所以我们不能用它声明任何对象。
等级制度
BlockingDeque 扩展自 BlockingQueue 接口,后者又扩展自Queue 接口和Deque 接口。
注意:Collection 框架的接口可能有额外的实现类和扩展接口,但上图只显示了 BlockingDeque 的层次结构及其实现类。
句法:
public interface BlockingDeque extends BlockingQueue, Deque
这里, E是集合中元素的类型。
实现 BlockingDeque 的类
BlockingDeque 的实现类是LinkedBlockingDeque 。这个类是BlockingDeque和链表数据结构的实现。 LinkedBlockingDeque 可以选择使用构造函数来限制,但是,如果未指定容量,则默认为Integer.MAX_VALUE 。节点在插入时动态添加,遵守容量限制。要在您的代码中使用 BlockingDeque,请使用此导入语句。
import java.util.concurrent.BlockingDeque;
(or)
import java.util.concurrent.*;
创建对象的语法:
LinkedBlockingDeque> objectName = new LinkedBlockingDeque>();
(or)
BlockingDeque> objectName = new LinkedBlockingDeque>();
示例:在下面给出的代码中,我们对 LinkedBlockingDeque 执行一些基本操作,例如创建对象、添加元素、删除元素以及使用迭代器遍历 LinkedBlockingDeque。
Java
// Java Program for BlockingDeque
import java.util.concurrent.*;
import java.util.*;
public class BlockingDequeExample {
public static void main(String[] args) {
// Instantiate an object using LinkedBlockingDeque named lbdq
BlockingDeque lbdq = new LinkedBlockingDeque();
// Add elements using add()
lbdq.add(134);
lbdq.add(245);
lbdq.add(23);
lbdq.add(122);
lbdq.add(90);
// Create an iterator to traverse the deque
Iterator lbdqIter = lbdq.iterator();
// Print the elements of lbdq on to the console
System.out.println("The LinkedBlockingDeque lbdq contains:");
for(int i = 0; i
Java
// Java Program for Adding elements to a LinkedBlockingDeque
import java.util.concurrent.*;
public class AddingElements {
public static void main(String[] args) {
// Instantiate a LinkedBlockingDeque named lbdq1
BlockingDeque lbdq1 = new LinkedBlockingDeque();
// Add elements using add()
lbdq1.add(145);
lbdq1.add(89);
lbdq1.add(65);
lbdq1.add(122);
lbdq1.add(11);
// Print the contents of lbdq1 on the console
System.out.println("Contents of lbdq1: " + lbdq1);
// Instantiate a LinkedBlockingDeque named lbdq2
LinkedBlockingDeque lbdq2 = new LinkedBlockingDeque();
// Add elements from lbdq1 using addAll()
lbdq2.addAll(lbdq1);
// Print the contents of lbdq2 on the console
System.out.println("\nContents of lbdq2: " + lbdq2);
}
}
Java
// Java Program for Accessing the elements of a LinkedBlockingDeque
import java.util.concurrent.*;
public class AccessingElements {
public static void main(String[] args) {
// Instantiate an object of LinkedBlockingDeque named lbdq
BlockingDeque lbdq = new LinkedBlockingDeque();
// Add elements using add()
lbdq.add(22);
lbdq.add(125);
lbdq.add(723);
lbdq.add(172);
lbdq.add(100);
// Print the elements of lbdq on the console
System.out.println("The LinkedBlockingDeque, lbdq contains:");
System.out.println(lbdq);
// To check if the deque contains 22
if(lbdq.contains(22))
System.out.println("The LinkedBlockingDeque, lbdq contains 22");
else
System.out.println("No such element exists");
// Using element() to retrieve the head of the deque
int head = lbdq.element();
System.out.println("The head of lbdq: " + head);
// Using peekLast() to retrieve the tail of the deque
int tail = lbdq.peekLast();
System.out.println("The tail of lbdq: " + tail);
}
}
Java
// Java Program for removing elements from a LinkedBlockingDeque
import java.util.concurrent.*;
public class RemovingElements {
public static void main(String[] args) {
// Instantiate an object of LinkedBlockingDeque named lbdq
BlockingDeque lbdq = new LinkedBlockingDeque();
// Add elements using add()
lbdq.add(75);
lbdq.add(86);
lbdq.add(13);
lbdq.add(44);
lbdq.add(10);
// Print the elements of lbdq on the console
System.out.println("The LinkedBlockingDeque, lbdq contains:");
System.out.println(lbdq);
// Remove elements using remove();
lbdq.remove(86);
lbdq.remove(44);
// Trying to remove an element
// that doesn't exist
// in the LinkedBlockingDeque
lbdq.remove(1);
// Print the elements of lbdq on the console
System.out.println("\nThe LinkedBlockingDeque, lbdq contains:");
System.out.println(lbdq);
}
}
Java
// Java Program to iterate through the LinkedBlockingDeque
import java.util.Iterator;
import java.util.concurrent.*;
public class IteratingThroughElements {
public static void main(String[] args) {
// Instantiate an object of LinkedBlockingDeque named lbdq
BlockingDeque lbdq = new LinkedBlockingDeque();
// Add elements using add()
lbdq.add(166);
lbdq.add(246);
lbdq.add(66);
lbdq.add(292);
lbdq.add(98);
// Create an iterator to traverse lbdq
Iterator lbdqIter = lbdq.iterator();
// Print the elements of lbdq on to the console
System.out.println("The LinkedBlockingDeque, lbdq contains:");
for(int i = 0; i
输出:
The LinkedBlockingDeque lbdq contains:
134 245 23 122 90
The element 23 has been removed
The LinkedBlockingDeque lbdq after remove operation contains:
[134, 245, 122, 90]
基本操作
1.添加元素
根据我们尝试使用的结构类型,可以以不同的方式将元素添加到 LinkedBlockedDeque 中。最常用的方法是 add() 方法,我们可以使用它在双端队列的末尾添加元素。我们还可以使用 addAll() 方法(这是 Collection 接口的一个方法)将整个集合添加到 LinkedBlockingDeque。如果我们希望将双端队列用作队列,我们可以使用 add() 和 put()。
Java
// Java Program for Adding elements to a LinkedBlockingDeque
import java.util.concurrent.*;
public class AddingElements {
public static void main(String[] args) {
// Instantiate a LinkedBlockingDeque named lbdq1
BlockingDeque lbdq1 = new LinkedBlockingDeque();
// Add elements using add()
lbdq1.add(145);
lbdq1.add(89);
lbdq1.add(65);
lbdq1.add(122);
lbdq1.add(11);
// Print the contents of lbdq1 on the console
System.out.println("Contents of lbdq1: " + lbdq1);
// Instantiate a LinkedBlockingDeque named lbdq2
LinkedBlockingDeque lbdq2 = new LinkedBlockingDeque();
// Add elements from lbdq1 using addAll()
lbdq2.addAll(lbdq1);
// Print the contents of lbdq2 on the console
System.out.println("\nContents of lbdq2: " + lbdq2);
}
}
Contents of lbdq1: [145, 89, 65, 122, 11]
Contents of lbdq2: [145, 89, 65, 122, 11]
2. 访问元素
可以使用 contains()、element()、peek()、poll() 访问 LinkedBlockingDeque 的元素。这些方法也有不同的变体,上表中给出了这些方法及其描述。
Java
// Java Program for Accessing the elements of a LinkedBlockingDeque
import java.util.concurrent.*;
public class AccessingElements {
public static void main(String[] args) {
// Instantiate an object of LinkedBlockingDeque named lbdq
BlockingDeque lbdq = new LinkedBlockingDeque();
// Add elements using add()
lbdq.add(22);
lbdq.add(125);
lbdq.add(723);
lbdq.add(172);
lbdq.add(100);
// Print the elements of lbdq on the console
System.out.println("The LinkedBlockingDeque, lbdq contains:");
System.out.println(lbdq);
// To check if the deque contains 22
if(lbdq.contains(22))
System.out.println("The LinkedBlockingDeque, lbdq contains 22");
else
System.out.println("No such element exists");
// Using element() to retrieve the head of the deque
int head = lbdq.element();
System.out.println("The head of lbdq: " + head);
// Using peekLast() to retrieve the tail of the deque
int tail = lbdq.peekLast();
System.out.println("The tail of lbdq: " + tail);
}
}
The LinkedBlockingDeque, lbdq contains:
[22, 125, 723, 172, 100]
The LinkedBlockingDeque, lbdq contains 22
The head of lbdq: 22
The tail of lbdq: 100
3. 删除元素
可以使用 remove() 从 LinkedBlockingDeque 中删除元素。其他方法,如 take() 和 poll() 也可以用于删除第一个和最后一个元素。
Java
// Java Program for removing elements from a LinkedBlockingDeque
import java.util.concurrent.*;
public class RemovingElements {
public static void main(String[] args) {
// Instantiate an object of LinkedBlockingDeque named lbdq
BlockingDeque lbdq = new LinkedBlockingDeque();
// Add elements using add()
lbdq.add(75);
lbdq.add(86);
lbdq.add(13);
lbdq.add(44);
lbdq.add(10);
// Print the elements of lbdq on the console
System.out.println("The LinkedBlockingDeque, lbdq contains:");
System.out.println(lbdq);
// Remove elements using remove();
lbdq.remove(86);
lbdq.remove(44);
// Trying to remove an element
// that doesn't exist
// in the LinkedBlockingDeque
lbdq.remove(1);
// Print the elements of lbdq on the console
System.out.println("\nThe LinkedBlockingDeque, lbdq contains:");
System.out.println(lbdq);
}
}
The LinkedBlockingDeque, lbdq contains:
[75, 86, 13, 44, 10]
The LinkedBlockingDeque, lbdq contains:
[75, 13, 10]
4. 遍历元素
要遍历 LinkedBlockingDeque 的元素,我们可以创建一个迭代器并使用 Iterable 接口的方法来访问元素,该接口是Java集合框架的根。 Iterable 的 next() 方法返回任何集合的元素。
Java
// Java Program to iterate through the LinkedBlockingDeque
import java.util.Iterator;
import java.util.concurrent.*;
public class IteratingThroughElements {
public static void main(String[] args) {
// Instantiate an object of LinkedBlockingDeque named lbdq
BlockingDeque lbdq = new LinkedBlockingDeque();
// Add elements using add()
lbdq.add(166);
lbdq.add(246);
lbdq.add(66);
lbdq.add(292);
lbdq.add(98);
// Create an iterator to traverse lbdq
Iterator lbdqIter = lbdq.iterator();
// Print the elements of lbdq on to the console
System.out.println("The LinkedBlockingDeque, lbdq contains:");
for(int i = 0; i
The LinkedBlockingDeque, lbdq contains:
166 246 66 292 98
BlockingDeque 的方法
BlockingDeque 接口有一个必须由每个实现类定义的各种方法。双端队列可以实现为队列和堆栈,因此 BlockingDeque 接口提供了执行相同操作的方法。下表提供了所有方法及其函数的列表。 Method Descriptionboolean add(E element) Adds the element to the queue represented by this deque (i.e. at the tail) if possible without violating any capacity restrictions. Returns true if the insertion is successful else throws an exception. void addFirst(E element) Adds the element at the head of the deque if possible without violating any capacity restrictions. If the operation is not successful then it throws an exception. void addLast(E element) Adds the element at the tail of the deque if possible without violating any capacity restrictions. If the operation is not successful then it throws an exception. boolean contains(Object o) Returns true if this deque contains the specified element. E element() Retrieves the head of the queue represented by this deque. Iterator Returns an iterator over the elements in this deque in the proper sequence. boolean offer(E element) Inserts the element into the queue represented by this deque (i.e. at the tail) if possible immediately without violating any capacity restrictions. Returns true on successful insertion and false otherwise. boolean offer(E element, long time, TimeUnit unit) Inserts the element into the queue represented by this deque (i.e. at the tail) immediately if possible, else waits for the time specified for the space to become available. boolean offerFirst(E element) Inserts the element at the head of the deque if possible immediately without violating any capacity restrictions. Returns true on successful insertion and false otherwise. boolean offerFirst(E element, long time, TimeUnit unit) Inserts the element at the head of the deque immediately if possible, else waits for the time specified for the space to become available. boolean offerLast(E element) Inserts the element at the tail of the deque if possible immediately without violating any capacity restrictions. Returns true on successful insertion and false otherwise. boolean offerLast(E element, long time, TimeUnit unit) Inserts the element at the tail of the deque immediately if possible, else waits for the time specified for the space to become available. E peek() Returns the head of the queue represented by this deque if present else returns null. E poll() Retrieves and removes the head of the queue represented by this deque if present else returns null. E poll(long time, TimeUnit unit) Retrieves and removes the head of the queue represented by this deque. If no element is present then it waits for the specified time for it to become available. E pollFirst(long time, TimeUnit unit) Retrieves and removes the head of the deque. If no element is present then it waits for the specified time for it to become available. E pollLast(long time, TimeUnit unit) Retrieves and removes the tail of the deque. If no element is present then it waits for the specified time for it to become available. void push(E e) Pushes an element onto the stack represented by this deque (in other words, at the head of this deque) if it is possible to do so immediately without violating capacity restrictions, throwing an IllegalStateException if no space is currently available. void put(E e) Inserts the specified element into the queue represented by this deque (in other words, at the tail of this deque), waiting if necessary for space to become available. void putFirst(E e) Inserts the specified element at the front of this deque, waiting if necessary for space to become available. void putLast(E e) Inserts the specified element at the end of this deque, waiting if necessary for space to become available. E remove() Retrieves and removes the head of the queue represented by this deque. boolean remove(Object obj) Removes the first occurrence of the specified element from the deque. boolean removeFirstOccurance(Object obj) Removes the first occurrence of the specified element from the deque. boolean removeLastOccurance(Object obj) Removes the last occurrence of the specified element from the deque. int size() Returns the number of elements in this deque. E take() Retrieves and removes the head of the queue represented by this deque. If required waiting for the element to become available. E takeFirst() Retrieves and removes the head of the deque. If required waiting for the element to become available. E takeLast() Retrieves and removes the tail of the deque. If required waiting for the element to become available.
这里,
- E – 集合中元素的类型。
- TimeUnit – 表示持续时间的枚举。
在接口Java.util.concurrent.BlockingQueue 中声明的方法
METHOD | DESCRIPTION |
---|---|
drainTo(Collection super E> c) | Removes all available elements from this queue and adds them to the given collection. |
drainTo(Collection super E> c, int maxElements) | Removes at most the given number of available elements from this queue and adds them to the given collection. |
remainingCapacity() | Returns the number of additional elements that this queue can ideally (in the absence of memory or resource constraints) accept without blocking, or Integer.MAX_VALUE if there is no intrinsic limit. |
在接口Java.util.Collection 中声明的方法
METHOD | DESCRIPTION |
---|---|
clear() | Removes all of the elements from this collection (optional operation). |
containsAll(Collection> c) | Returns true if this collection contains all of the elements in the specified collection. |
equals(Object o) | Compares the specified object with this collection for equality. |
hashCode() | Returns the hash code value for this collection. |
isEmpty() | Returns true if this collection contains no elements. |
parallelStream() | Returns a possibly parallel Stream with this collection as its source. |
removeAll(Collection> c) | Removes all of this collection’s elements that are also contained in the specified collection (optional operation). |
removeIf(Predicate super E> filter) | Removes all of the elements of this collection that satisfy the given predicate. |
retainAll(Collection> c) | Retains only the elements in this collection that are contained in the specified collection (optional operation). |
spliterator() | Creates a Spliterator over the elements in this collection. |
stream() | Returns a sequential Stream with this collection as its source. |
toArray() | Returns an array containing all of the elements in this collection. |
toArray(IntFunction | Returns an array containing all of the elements in this collection, using the provided generator function to allocate the returned array. |
toArray(T[] a) | Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the specified array. |
在接口Java.util.Deque 中声明的方法
METHOD | DESCRIPTION |
---|---|
addAll(Collection extends E> c) | Adds all of the elements in the specified collection at the end of this deque, as if by calling addLast(E) on each one, in the order that they are returned by the collection’s iterator. |
descendingIterator() | Returns an iterator over the elements in this deque in reverse sequential order. |
getFirst() | Retrieves, but does not remove, the first element of this deque. |
getLast() | Retrieves, but does not remove, the last element of this deque. |
peekFirst() | Retrieves, but does not remove, the first element of this deque, or returns null if this deque is empty. |
peekLast() | Retrieves, but does not remove, the last element of this deque, or returns null if this deque is empty. |
pollFirst() | Retrieves and removes the first element of this deque, or returns null if this deque is empty. |
pollLast() | Retrieves and removes the last element of this deque, or returns null if this deque is empty. |
pop() | Pops an element from the stack represented by this deque. |
removeFirst() | Retrieves and removes the first element of this deque. |
removeLast() | Retrieves and removes the last element of this deque. |
在接口Java .lang.Iterable 中声明的方法
METHOD | DESCRIPTION |
---|---|
forEach(Consumer super T> action) | Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception. |
BlockingDeque 方法的行为
以下是 BlockingDeque 提供的用于对双端队列进行插入、删除和检查操作的方法。如果请求的操作没有立即得到满足,这四组方法中的每一个都会表现不同。
- 抛出异常:如果请求的操作没有立即得到满足,将抛出异常。
- 特殊值:如果没有立即满足操作,则返回一个特殊值。
- 阻塞:如果尝试的操作没有立即满足,则方法调用被阻塞,并等待直到它被执行。
- 超时:返回一个特殊值,告诉操作是否成功。如果请求的操作无法立即执行,则方法调用会阻塞,直到可以执行,但等待时间不会超过给定的超时时间。
Methods on First Element (Head of Deque) Methods on Last Element (Tail of Deque)Operation Throws Exception Special value Blocks Times out Insert addFirst(e) offerFirst(e) putFirst(e) offerFirst(e, timeout, timeunit) Remove removeFirst() pollFirst() takeFirst() pollFirst(timeout, timeunit) Examine getFirst() peekFirst() not applicable not applicable Operation Throws Exception Special value Blocks Times out Insert addLast(e) offerLast(e) putLast(e) offerLast(e, timeout, timeunit) Remove removeLast() pollLast() takeLast() pollLast(timeout, timeunit) Examine getLast() peekLast() not applicable not applicable
我们知道我们可以在 BlockingDeque 中从两个方向插入、删除和检查元素。由于BlockingDeque扩展了 BlockingQueue,因此 BlockingDeque 上作用于一个方向的插入、删除和检查操作的方法与 BlockingQueue 类似。以下比较说明相同。 Operation BlockingQueue Method Equivalent BlockingDeque MethodInsert add(e) addLast(e) offer(e) offerLast(e) put(e) putLast(e) offer(e, time, unit) offerLast(e, time, unit) Remove remove() removeFirst() poll() pollFirst() take() takeFirst() poll(time, unit) pollFirst(time, unit) Examine element() getFirst() peek() peekFirst()
参考: Java : Java