Stack
Stack是Vector的子类,它用于模拟“棧”这种数据结构,“棧”通常是指“后进先出”(LIFO)的容器。最后“push”进棧的元素,将最先被“pop”出棧。进棧出棧的都是Object,因此从棧中取出元素后必须进行类型转换。
Stack提供方法:
- Object peek()
返回棧的第一个元素,但并不将钙元素”pop”出棧。 - Object pop()
返回棧的第一个元素,并将该元素”pop”出棧。 - void push(Object item)
将一个元素”push”进棧,最后一个进棧的元素总是位置棧顶。
由于Stack集成了Vector,因此它也是一个非常古老的Java集合类,它同样是线程安全的、性能较差,因此尽量少用Stack类。如果需要请用ArrayDeque。
ArrayDeque 是List的实现类,ArrayDeque既实现了List接口,也实现了Deque接口,由于实现的Deque接口,因此可以作为棧来使用;而且ArrayDeque 底层也是基于数组的实现,因此性能也很好。
Queue
Queue用于模拟队列这种数据结构,队列通常是指“先进先出”(FIFO)的容器。
队列的头部保存在队列中存放时间最长的元素,队列的尾部保存在队列中存放时间最短的元素。新元素插入(offer)到队列的尾部,访问元素(poll)操作会返回队列头部的元素。
注意,队列不允许随机访问队列中的元素。
Queue解耦中定义了如下方法:
- void add(Object o)
将指定元素加入此队列的尾部。 - Object element()
获取队列头部元素,但不删除该元素。 - boolean offer(Object o)
将指定元素加入此队列的尾部。当使用有容量限制的队列时,此方法通常比add(Object e)方法更好。 - Object peek()
获取队列头部元素,但不删除该元素。如果队列为空,则返回null。 - Object poll()
获取队列头部元素,并删除该元素。如果队列为空,则返回null。 Object remove()
获取队列的头部元素,并删除该元素。列表内容
Queue解耦只有一个PriorityQueue实现类。除此之外,Queue还有一个Deque接口,
Deque代表一个“双端队列”,双端队列可以同事对两端来添加、删除元素,因此Deque的实现类既可当成队列使用,也可当成棧使用。
PriorityQueue
PriorityQueue是一个比较标准的队列实现类。之所以说它是比较标准的队列实现类,而不是绝对标准的队列实现类,是因为PriorityQueue保存队列元素顺序并不是按加入队列的顺序,而是按队列元素大小进行重新排序。因此嗲用peek()方法或poll()方法取出队列中元素时,并不是取出最先进入队列的元素,而是取出队列中最小的元素。
注意:PriorityQueue已经违反了队列的最基本规则:先进先出(FIFO)。
示例:
package com.queue;
import java.util.PriorityQueue;
public class QueueOrDueueTest {
public static void main(String[] args) {
PriorityQueue queue = new PriorityQueue();
queue.offer(2);
queue.offer(12);
queue.offer(-2);
queue.offer(5);
System.out.println(queue);//[-2, 5, 2, 12]
System.out.println(queue.poll());//访问第一个其实是访问最小的一个 -2
System.out.println(queue.poll());//2
System.out.println(queue.poll());//5
System.out.println(queue);//[12]
}
}
程序多次调用queue.poll()方法,即可看到元素按从小到大的顺序“移出队列”。
自然排序:
采用自然数需的PriorityQueue 集合中的元素必须实现Comparable接口,而且应该是同一类的多个实例,否则抛出ClassCaseException。
定制排序:
创建PriorityQueue 队列时,传入一个Comparator对象,该对象负责队列中的所有元素进行排序。采用定制排序时不需要队列元素实现Comparable接口。
Deque 接口和ArrayDeque
Deque接口是Queue接口的子接口,它代表一个双端队列,Deque接口里定义了一些双端队列的方法,这些方法允许从两端来操作队列的元素。
- void addFirst(Object o)
将指定元素插入到双端队列的开头。 - void addLast(Object o)
将指定元素插入到双端队列的末尾。 - Iterator descendingIterator()
返回双端队列对应的迭代器,该迭代器将以逆向顺序来迭代队列中的元素。 - Object getFirst()
获取但不删除双端队列的第一个元素。 - Object getLast()
获取但不删除双端队列的最后一个元素。 - boolean offerFirst(Object o)
将指定元素插入到双端队列的开头。 - boolean offerLast(Object o)
将指定元素插入到双端队列的末尾。 - Object peekFirst()
获取但不删除该双端队列的第一个元素,如果双端队列为空,则返回null。 - Object peekLast()
获取但不删除该双端队列的最后一个元素,如果双端队列为空,则返回null。 - Object pollFirst()
获取并删除该双端队列的第一个元素,如果双端队列为空,则返回null。 - Object pollLast()
获取并删除该双端队列的最后一个元素,如果双端队列为空,则返回null。 - Object pop()
pop出该双端队列所标识的棧的棧顶元素。相当于removeFirst()。 - void push(Object o)
将一个元素push进该双端队列所标识的棧的栈顶。相当于addFirst(e)。 - Object removeFirst()
获取并删除该双端队列的第一个元素。 - Object removeFirstOccurrence(Object o)
删除该双端队列的第一次出现的元素o。 - Object removeLast()
获取并删除该双端队列的最后一个元素。 - boolean removeLastOccurrence(Object o)
删除该双端队列的最后一次出现的元素o。
注意:
ArrayDeque,它是基于数组实现的双端队列,创建Deque是同样可指定一个numElements参数,该参数用于指定Object[]数组的长度;如果不指定numElements参数 ,Deque底层数组长度为16。
ArrayDeque作为棧
程序中需要使用“棧”这种数据结构时,推荐使用ArrayDeque,尽量避免使用Stack(太古老,性能差)。
示例:
package com.queue;
import java.util.ArrayDeque;
public class ArrayDequeTest {
public static void main(String[] args) {
ArrayDeque stack = new ArrayDeque();
stack.push("JAVA");
stack.push("JS");
stack.push("C++");
System.out.println(stack);
//输出:[C++, JS, JAVA]
//访问第一个元素,但不将其弹出棧
System.out.println(stack.peek());
//输出:C++
System.out.println(stack.pop());
//输出:C++
System.out.println(stack);
//输出:[JS, JAVA]
}
}
ArrayDeque作为队列
按照“先进先出”的方式操作集合元素
示例:
public static void main(String[] args) {
ArrayDeque queue = new ArrayDeque();
queue.offer("JAVA");
queue.offer("JS");
queue.offer("C++");
System.out.println(queue);
//输出:[JAVA, JS, C++]
//访问队列头部元素,但不将其poll出队列"棧",输出:JAVA
System.out.println(queue.peek());
//poll出第一个元素,输出:JAVA
System.out.println(queue.poll());
System.out.println(queue);
//输出:[JS, C++]
}