Queue集合
Queue 用于模拟队列这种数据结构,队列通常是指"先进先出" (FIFO) 的容器 。 队列的头部保存在队列中存放时间最长的元素 , 队列的尾部保存在队列中存放时间最短的元素 。 新元素插入 (offer ) 到
队列的尾部,访问元素 (poll ) 操作会返回队列头部的元素 。 通常 , 队列不允许随机访问队列中的元素。
Queue集合提供的API方法
void add(Object e): 将指定元素加入此队列的尾部。
Object element() : 获取队列头部的元素 ,但是不删除该元素 。
boolean offer(Object e) : 将指定元素加入此队列的尾部 。 当使用有容量限制的队列时,此方法通常比 add(Object e)方法更好 。
Object peek(): 获取队列头部的元素 , 但是不删除该元素 。 如果此队列为空,则返回 null 。
Object poll(): 获取队列头部的元素 , 并删除该元素。如果此队列为空 , 则返回 null 。
Object remove() : 获取队列头部的元素 , 并删除该元素 。
PriorityQueue 实现类
PriorityQueue 保存队列元素的顺序并不是按加入队列的顺序,而是按队列元素 的大小进行重新排序 。 因此当调用 peek()方法或者 poll()方法取出队列中的元素时,并不是取出最先进入队列的元素 , 而是取出队列中最小的元素。
实例代码:
import java.util.PriorityQueue;
/**
* @author: 随风飘的云
* @date 2022/03/19 14:51
*/
public class PriorityQueueTest {
public static void main(String[] args) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
queue.add(2);
queue.add(1);
queue.add(-1);
queue.add(10);
System.out.println(queue);
System.out.println(queue.poll());
System.out.println(queue.poll());
}
}
结果:
Deque 接口与 ArrayDeque 实现类
Deque接口
Deque接口是 Queue接口的子接口 , 它代表一个双端队列, Deque 接口里定义了 一些双端队列的方法,这些方法允许从两端来操作队列的元素 。
void addFirst(Object e): 将指定元素插入该双端队列的开头。
void addLast(Object e): 将指定元素插入该双端队列的末尾 。
Iterator descendingIterator(): 返回该双端队列对应的迭代器,该法代器将以逆向顺序来迭代队列中的元素
Object getFirst(): 获取但不删除双端队列的第一个元素 。
Object getLast(): 获取但不删除双端队列的最后一个元素 。
boolean offerFirst(Object e): 将指定元素插入该双端队列的开头 。
boolean offerLast(Object e): 将指定元素插入该双端队列的末尾。
Object peekFirst(): 获取但不删除该双端队列的第 一个元素:如果此双端队列为空 , 则返回 null 。
Object peekLast(): 获取但不删除该双端队列的最后 一个元素:如果此双端队列为空,则返回 null 。
Object pollFirst(): 获取并删除该双端队列的第 一个元素;如果此双端队列为空,则返回 null 。
Object pollLast(): 获取并删除该双端队列的最后 一个元素;如果此双端队列为空, 则 返回 null 。
Object pop() (栈方法) : pop 出该双端队列所表示的梭的技顶元素 。 相当于 removeFirst() 。
void push(Object e) (战方法) : 将 一 个元素 push 进该双端队列所表示的拢的技顶 。 相当于addFirst(e) 。
Object removeFirst(): 获取并删除该双端队列的第一个元素。
Object removeFirstOccurrence(Object 0): 删除该双端队列的第 一 次出现的元素 。
Object removeLast(): 获取并删除该双端队列的最后一个元素 。
boolean removeLastOccurrence(Object 0): 删除该双端队列的最后 一 次出现的元素 。
ArrayDeque类
基于数组实现的双端队列,创建 Deque 时同样可指定一个 numElements 参数 , 该参数用于指定 Object[]数组的长度 ;如果不指定 numElements 参数, Deque 底层数组的长度为 16 。
实例代码
import java.util.ArrayDeque;
/**
* @author: 随风飘的云
* @date 2022/03/19 15:15
*/
public class ArrayDequeStack {
public static void main(String[] args) {
ArrayDeque stack = new ArrayDeque();
// 依次将三个元素push入"栈"
stack.push("我要疯狂了。");
stack.push("JVM结构");
stack.push("疯狂成人");
// 输出
System.out.println(stack);
// 访问第一个元素,但并不将其pop出"栈"
System.out.println(stack.peek());
// 测试结果输出
System.out.println(stack);
// pop出第一个元素,
System.out.println(stack.pop());
System.out.println(stack);
}
}
结果:
LinkedList 实现类
LinkedList是一 个List 集合 ,可以根据索引来随机访问集合中的元素 。 除此之外, LinkedList 还实现了 Deque 接口,可以被当成双端队列来使用,因此既可以被当成栈来使用 ,也可以当成队列使用 。
实例代码:
import java.util.LinkedList;
/**
* @author: 随风飘的云
* @date 2022/03/19 15:20
*/
public class LinkedListTest {
public static void main(String[] args) {
LinkedList books = new LinkedList();
// 将字符串元素加入队列的尾部
books.offer("疯狂Java讲义");
// 将一个字符串元素加入栈的顶部
books.push("轻量级Java EE企业应用实战");
// 将字符串元素添加到队列的头部(相当于栈的顶部)
books.offerFirst("疯狂Android讲义");
// 以List的方式(按索引访问的方式)来遍历集合元素
for (int i = 0; i < books.size() ; i++ )
{
System.out.println("遍历中:" + books.get(i));
}
// 访问、并不删除栈顶的元素
System.out.println(books.peekFirst());
// 访问、并不删除队列的最后一个元素
System.out.println(books.peekLast());
// 将栈顶的元素弹出“栈”
System.out.println(books.pop());
// 下面输出将看到队列中第一个元素被删除
System.out.println(books);
// 访问、并删除队列的最后一个元素
System.out.println(books.pollLast());
// 下面输出:[轻量级Java EE企业应用实战]
System.out.println(books);
}
}
结果:
线性表的性能分析
Java 提供的 List 就是一个线性表接口,而 ArrayList 、 LinkedList 又是线性表的两种典型实现 : 基于数组的线性表和基于链的线性表。 Queue 代表了队列, Deque 代表了双端队列(既可作为队列使用, 也可作为找使用) ,接下来对各种实现类的性能进行分析 。
一般来说,由于数组以一块连续内存区来保存所有的数组元素,所以数组在随机访问时性能最好,所有的内部以数组作为底层实现的集合在随机访问时性能都比较好;而内部以链表作为底层实现的集合在执行插入、删除操作时有较好的性能。但总体来说, ArrayList 的性能比 LinkedList 的性能要好,因此大部分时候都应该考虑使用ArrayList 。
使用List集合建议:
1、 如果需要遍历 List 集合元素,对于 ArrayList 、 Vector 集合,应该使用随机访问方法 (get)
来遍历集合元素,这样性能更好;对于 LinkedList 集合,则应该采用法代器 (lterator) 来遍历集合元素 。2、 如果需要经常执行插入、删除操作来改变包含大量数据 的 List 集合的大小,可考虑使用LinkedList 集合 。 使用 ArrayList 、 Vector 集合可能需要经常重新分配内部数组的大小, 效果可能较差 。
3、 如果有多个线程需要同 时访问 List 集合中的元素,开发者可考虑使用Collections 将集合包装成线程安全的集合 。