Java——Java集合Queue

7 篇文章 0 订阅

本文根据疯狂Java讲义(第3版)整理而成,感谢作者李刚老师

如果觉得内容不错的话,推荐大家买一本阅读,绝对物超所值哦

阅读本文前可以先看Java——Java集合概述 Java——Java集合List

四、Queue集合

Queue集合用于模拟队列这种数据结构,队列通常是先进先出的容器。头部保存在队列中存放时间最长的元素,尾部保存存放时间最短的元素。新元素插入到队列尾部,访问元素会返回队列头部的元素。

一、Queue接口

1.Queue接口定义了如下i几个方法:

  • void add(Object e): 将指定元素加入到队列尾部。
  • Object element(): 获取队列头部的元素,但是不删除该元素。
  • boolean offer(Object e): 将指定元素加入到队列尾部。此方法优于add(Object e)。
  • Object peek(): 获取队列头部的元素,但是不删除该元素。如果队列为空,返回null。
  • Object poll(): 获取队列头部的元素,并删除该元素。如果队列为空,返回null。
  • Object remove(): 获取队列头部的元素,并删除该元素。

2.Queue接口有一个PriorityQueue实现类。除此之外,Queue还有一个Deque接口,Deque代表一个双端队列,双端队列可以通知从两段来添加、删除元素,因此Deque的实现类即可当作队列使用,也可以当成栈使用。Java为Deque提供了ArrayDeque和LinkedList两个实现类。

二、PriorityQueue实现类

1.PriorityQueue是一个比较标准的队列实现类。但是它保存队列元素的顺序并不是按加入队列的顺序,而是按队列元素的大小进行重新排序。优先级高的排在前面,优先级低的排在后面。因此当调用peek()或poll()方法取出队列中的元素时,并不是取出最先进入队列的元素,二是取出队列中优先级最高的元素。(从这一点看PriorityQueue已经违反了队列的基本规则:先进先出)

public PriorityQueueTest{
    public static void main(String[] args){
        PriorityQueue pq = new PriorityQueue();
        pq.offer(6);
        pq.offer(-3);
        pq.offer(9);
        pq.offer(20);
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        // 将会输出-3 6 9 20
    }
}

所示代码中PriorityQueue没有给定排序方式,队列按自然排序升序方式保存元素(越小的元素优先级越高),输出时按从小到大输出。

2.PriorityQueue不允许插入null元素,因为它需要对队列元素进行排序。排序方式有两种:

  • 自然排序:采用自然排序的PriorityQueue集合中的元素类型必须实现了ComParable接口,而且应该是同一个类的实例。(同TreeSet,参考Java——Java集合Set
  • 定制排序:创建PriorityQueue队列时,传入一个Comparator对象,该对象负责对队列中的所有元素进行排序。(同TreeSet)

三、Deque接口与ArrayDeque,LinkedList实现类

1.Deque接口是Queue接口的子接口,它代表一个双端队列,Deque接口里定义了一些双端队列的方法,这些方法允许从两端来操作队列的元素。方法如下,

  • void addFirst(Object e):Java在线API中文文档 - 开源中国
  • void addLast(Object e):
  • Iterator descendingIterator():
  • Object getFirst():
  • Object getLast():
  • boolean offerFirst(Object e):
  • boolean offerLast(Object e):
  • Object peekFirst():
  • Object peekLast():
  • Object pollFirst():
  • Object pollLast():
  • Object pop()(栈方法):
  • void push(Object e)(栈方法):
  • Object removeFirst():
  • Object removeFirstOccurrence(Object o):
  • Object removeLast():
  • Object removeLastOccurrence(Object o):

2.ArrayDeque是Deque接口的一个典型的实现类:,它基于数组Object[]实现。创建Deque时可指定一个numElements参数(数组长度),如果不指定的话数组长度默认为16。当集合元素超过数组容量时,系统会自动分配一个更大容量的Object[]数组来存储集合元素。ArrayDeque既可以当作栈使用(避免使用Stack),也可以当作队列使用。

3.LinkedList是Deque接口的另一个实现类,可以当作双端队列使用,既可作为栈,也可作为队列。同时,它还实现了List接口,也是一个List集合。LinkedList是一个功能非常强大的集合类。

4.LinkedList与ArrayList、ArrayDeque的实现机制完全不同。ArrayList、ArrayDeque内以数组的形似来保存集合中的元素,因此随机访问时有较好的性能;而LinkedList内部以链表的形式来保存元素,因此随机分访问集合元素时性能较差,但在插入,删除元素时性能比较出色。需要指出的是,虽然Vector也是以数组的形式来存储集合元素的,但因为它实现了线程同步功能(而且实现机制也不好),所以各方面性能都比较差。

四、各种线性表的比较和分析

Java提供的List就是一个线性表接口,而ArrayList、LinkedList又是线性表的两种典型的实现;基于数组的线性表和基于链的线性表。Queue代表了队列,也是线性表。Deque代表了双端队列(既可作为队列使用,也可以作为栈使用),接下来对各种实现类的性能进行分析。

初学者可以无须理会ArrayList和LinkedList之间的性能差异,只需要知道LinkedList集合不仅提供了List的功能,还提供了双端队列、栈的功能就行。但对于一个成熟的Java程序员,在一些性能非常敏感的地方,可能需要慎重选择哪个List实现。

一般来说,由于数组以一块连续内存区来保存所有的数组元素,所以数组在随机访问时性能最好,所有的内部以数组作为底层实现的集合在随机访问时性能都比较好;而内部以链表作为底层实现的集合在执行插入、删除操作时有较好的性能。但总体来说,ArrayList的性能比LinkedList的性能要好,因此大部分时候都应该考虑使用ArrayList。

关于使用List集合有如下建议。

如果需要遍历List集合元素,对于ArrayList、Vector集合,应该使用随机访问方法(get)来遍历集合元素,这样性能更好;对于LinkedList集合,则应该采用迭代器(Iterator)来遍历集合元素。

如果需要经常执行插入、删除操作来改变包含大量数据的List集合的大小,可考虑使用LinkedList集合。使用ArrayList、Vector集合可能需要经常重新分配内部数组的大小,效果可能较差。

如果有多个线程需要同时访问List集合中的元素,开发者可考虑使用Collections将集合包装成线程安全的集合。
——李刚老师


1.疯狂Java讲义(第3版)
2.Java在线API中文文档 - 开源中国

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值