Java面向对象系列[v1.0.0][Queue]

Queue用于模拟队列这种数据结构,队列通常是指”先进先出“(FIFO)的容器,队列的头部保存队列中存放时间最长的元素,队列的尾部保存队列中存放时间最短的元素;新元素插入到队列的尾部,访问元素操作会返回队列头部的元素;通常情况下队列不允许随机访问队列中的元素。

Queue接口方法

  • 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()方法取出队列中的元素时,并不是取出最先进入队列的元素,而是取出队列中最小的元素,从这个意义上来说它已经违反了先进先出(FIFO)的规则

package democollection;
import java.util.*;
import static java.lang.System.*;

public class PriorityQueueTest
{
    public static void main(String[] args)
    {
        var pq = new PriorityQueue();
        // 下面代码依次向pq中加入四个元素
        pq.offer(6);
        pq.offer(-3);
        pq.offer(20);
        pq.offer(18);
        // 输出pq队列,并不是按元素的加入顺序排列
        // 输出[-3, 6, 20, 18]
        out.println(pq);
        // 访问队列第一个元素,其实就是队列中最小的元素:-3
        out.println(pq.poll());
    }
}
  • PriorityQueue不允许插入null元素
  • priorityQueue有两种排序方式,自然排序:采用自然顺序的PriorityQueue集合中的元素必须实现了Comparable接口,而且应该是同一个类的多个实例,否则可能导致ClassCastException异常;订制排序:创建PriorityQueue队列时,传入一个Comparator对象,该对象负责对队列中的所有元素进行排序,采用定制排序时不要求队列元素实现Comparable接口;PriorityQueue队列对元素的要求与TreeSet对元素的要求基本一致,关于自然排序和定制排序也基本一致

Deque接口与ArrayDeque实现类

Deque接口是Queue接口的子接口,它代表一个双端队列并提供了两段操作队列的方法:

  • void addFirst(Object e):将指定元素插入该双端队列的开头
  • void addLast(Object e):将指定元素插入该双端队列的末尾
  • Iterator descendingIterator():返回该双端队列对应的迭代器,该迭代器将以逆向顺序来迭代队列中的元素
  • Object getFirst():获取但不删除双端队列的第一个元素
  • Object getLast():获取但不删除双端队列的最后一个元素
  • boolean offerFirst():将指定元素插入该双端队列的开头
  • boolean offerLast():将指定元素插入该双端队列的末尾
  • 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 o):删除该双端队列的第一次出现的元素o
  • Object removeLast():获取并删除该双端队列的最后一个元素
  • boolean removeLastOccurrence(Object o):删除该双端队列的最后一次出现的元素o

Deque不仅可以当成双端队列使用,还可以当作栈来使用

Deque的方法与Queue方法对照

在这里插入图片描述

Deque方法与Stack的方法对照

在这里插入图片描述

ArrayDeque

ArrayDeque是Deque接口的典型实现类,它是一个基于数组实现的双端队列,创建Deque时同样可指定一个numElements参数,该参数用于指定Object[]数组的长度,如果不指定该参数则Deque底层数组的长度为16
ArrayList和ArrayDeque两个集合类的实现机制基本相似,他们底层都采用一个动态的、可重分配的Object[]数组来存储集合元素,当集合元素超出了该数组的容量时,系统会在底层重新分配一个Object[]数组来存储集合元素

将ArrayDeque当成栈来使用

package democollection;
import java.util.*;
import static java.lang.System.*;
public class ArrayDequeStack
{
    public static void main(String[] args)
    {
        var stack = new ArrayDeque();
        // 依次将三个元素push入"栈"
        stack.push("Sprint实战");
        stack.push("SprintBoot实战");
        stack.push("Spring微服务实战");
        // 输出:[Spring微服务实战, SprintBoot实战, Sprint实战]
        out.println(stack);
        // 访问第一个元素,但并不将其pop出"栈",输出:Spring微服务实战
        out.println(stack.peek());
        // 依然输出:[Spring微服务实战, SprintBoot实战, Sprint实战]
        out.println(stack);
        // pop出第一个元素,输出:Spring微服务实战
        out.println(stack.pop());
        // 输出:[SprintBoot实战, Sprint实战]
        out.println(stack);
    }
}

程序中需要使用栈这种数据结构时,推荐使用的是ArrayDeque而不是Stack,因为Stack性能差太古老

将ArrayDeque当成队列使用

package democollection;
import java.util.*;
import static java.lang.System.*;

public class ArrayDequeQueue
{
    public static void main(String[] args)
    {
        var queue = new ArrayDeque();
        // 依次将三个元素加入队列
        queue.offer("Sprint实战");
        queue.offer("SprintBoot实战");
        queue.offer("Spring微服务实战");
        // 输出:[Sprint实战, SprintBoot实战, Spring微服务实战]
        out.println(queue);
        // 访问队列头部的元素,但并不将其poll出队列"栈",输出:Sprint实战
        out.println(queue.peek());
        // 依然输出:[Sprint实战, SprintBoot实战, Spring微服务实战]
        out.println(queue);
        // poll出第一个元素,输出:Sprint实战
        out.println(queue.poll());
        // 输出:[SprintBoot实战, Spring微服务实战]
        out.println(queue);
    }
}

LinkedList实现类

LinkedList类是List接口的实现类,这意味着它是一个List集合,可以根据索引来随机访问集合中的元素,除此之外LinkedList还实现了Deque接口,可以被当成双端队列来使用,因此既可以被当成栈来用,也可以当成队列使用

package democollection;
import java.util.*;
import static java.lang.System.*;

public class LinkedListTest
{
    public static void main(String[] args)
    {
        var books = new LinkedList();
        // 将字符串元素加入队列的尾部
        books.offer("询盘云Web自动化测试");
        // 将一个字符串元素加入栈的顶部
        books.push("询盘云UI自动化测试");
        // 将字符串元素添加到队列的头部(相当于栈的顶部)
        books.offerFirst("询盘云测试平台");
        // 以List的方式(按索引访问的方式)来遍历集合元素
        for (var i = 0; i < books.size(); i++)
        {
            out.println("遍历中:" + books.get(i));
        }
        // 访问、并不删除栈顶的元素
        out.println(books.peekFirst());
        // 访问、并不删除队列的最后一个元素
        out.println(books.peekLast());
        // 将栈顶的元素弹出“栈”
        out.println(books.pop());
        // 下面输出将看到队列中第一个元素被删除
        out.println(books);
        // 访问、并删除队列的最后一个元素
        out.println(books.pollLast());
        // 下面输出:[询盘云UI自动化测试]
        out.println(books);
    }
}

代码中分别示范了LinkedList作为List集合、双端队列、栈的用法,由此可见LinkedList是个功能强大的集合类

LinkedList与ArrayList、ArrayDeque区别

  • LinkedList与ArrayList、ArrayDeque的实现机制完全不同,ArrayList和ArrayDeque内部以数组的形式来保存集合中的元素,再随机访问集合元素时有较好的性能
  • LinkedList内部以链表的形式来保存集合中的元素,随机访问集合元素时性能较差,但在插入、删除元素时性能较好
  • Vector也是以数组的形式来存储集合元素,但它实现了线程同步功能,因此各方面性能较差

各种线性表性能分析

Java提供的List就是一个线性表接口,而ArrayList、LinkedList又是线性表的两种典型实现:基于数组的线性表和基于链的线性表,Queue代表了队列,Deque代表了双端队列(可做队列也可以作为栈使用)

  • 由于数组以一块连续内存区来保存所有的数组元素,所以数组在随机访问数组元素时表现的性能最好,所有内部以数组作为底层实现的集合随机访问时性能都比较好
  • 内部以链表作为底层实现的集合在执行插入、删除操作时性能更好,但总体来说ArrayList性能比LinkedList性能更好
  • 如果需要遍历List集合元素,对于ArrayList、Vector集合,应该使用随机访问方法(get)来遍历集合元素,这样性能更好;对于LinkedList集合,则应采用迭代器Iterator来遍历集合元素
  • 如果需要经常执行插入、删除操作来改变包含大量数据的List集合的大小,可考虑使用LinkedList集合;使用ArrayList、Vector集合可能需要经常重新分配内部数组大小,效果较差
  • 如果多个线程需要同时访问List集合中的元素,可考虑使用Collections将集合包装成线程安全的集合
发布了207 篇原创文章 · 获赞 124 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/dawei_yang000000/article/details/105184774