当前位置 : 主页 > 编程语言 > java >

Java集合面试之Queue篇

来源:互联网 收集:自由互联 发布时间:2023-09-03
Java集合面试之Queue篇 (qq.com) 1、队列是什么? 队列是常用数据结构之一。是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入

Java集合面试之Queue篇 (qq.com)

1、队列是什么?

队列是常用数据结构之一。是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,故为先进先出(FIFO,first in first out)线性表。

和栈一样,队列是一种操作受限制的线性表。

2、队列的分类?

Queue 大体可分为以下几类:

双端队列:双端队列Deque是 Queue 的子类也是 Queue 的补充类,头部和尾部都支持元素插入和获取。

阻塞队列:阻塞队列指的是在元素操作时(添加或删除),如果没有成功,会阻塞等待执行。例如,当添加元素时,如果队列元素已满,队列会阻塞等待直到有空位时再插入。有BlockingQueue、LinkedBlockingQueue、ArrayBlockingQueue和DelayQueue。

非阻塞队列:非阻塞队列会直接返回操作的结果。双端队列也属于非阻塞队列。如ConcurrentLinkedQueue。

优先级队列:PriorityQueue 一个基于优先级堆的无界优先级队列。

并发队列:有阻塞队列和非阻塞队列,前者使用锁实现,后者则使用CAS非阻塞算法实现,使用非阻塞队列一般性能比较好。

3、Java中队列有哪些?有什么区别?

(1)内置的非阻塞队列:PriorityQueue 和 ConcurrentLinkedQueue;

  • PriorityQueue 类实质上维护了一个有序列表。加入到 Queue 中的元素根据它们的天然排序(通过 java.util.Comparable 实现)或者根据传递给构造函数的java.util.Comparator 实现来定位。

  • ConcurrentLinkedQueue 是基于链接节点的、线程安全的队列。并发访问不需要同步。因为它在队列的尾部添加元素并从头部删除它们,所以只要不需要知道队列的大小,对公共集合的共享访问做得很好。收集关于队列大小的信息会很慢,需要遍历队列。

(2)实现阻塞接口的:java.util.concurrent 中加入了 BlockingQueue 接口和五个阻塞队列类。它不是立即从队列中添加或者删除元素,没有空间入或者没有元素出时,线程执行操作阻塞。五个队列所提供的各有不同:

  • ArrayBlockingQueue :一个由数组支持的有界队列。

  • LinkedBlockingQueue :一个由链接节点支持的可选有界队列。

  • PriorityBlockingQueue :一个由优先级堆支持的无界优先级队列。

  • DelayQueue :一个由优先级堆支持的、基于时间的调度队列。

  • SynchronousQueue :一个利用 BlockingQueue 接口的简单聚集(rendezvous)机制。

4、有界队列和无界队列的区别?

有界队列:有固定大小的队列叫做有界队列,比如:new ArrayBlockingQueue(6),6 就是队列的大小。

无界队列:指的是没有设置固定大小的队列,这些队列的特点是可以直接入列,直到溢出。它们并不是真的无界,它们最大值通常为 Integer.MAXVALUE,只是平常很少能用到这么大的容量(超过 Integer.MAXVALUE),因此从使用者的体验上,就相当于 无界。

5、BlockingQueue是什么?

  • 在进行检索或移除一个元素的时候,它会等待队列变为非空;
  • 当添加元素时,它会等待队列中的可用空间。

BlockingQueue接口属于集合框架,主要用于实现生产者-消费者模式。我们不需要担心等待生产者有可用的空间,或消费者有可用的对象,因为它都在BlockingQueue的实现类中被处理了。常见实现类有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue等。

6、ArrayBlockingQueue 与 LinkedBlockingQueue 的区别

  1. 队列中锁的实现不同,ArrayBlockingQueue实现的队列中的锁是没有分离的,即生产和消费用的是同一个锁;LinkedBlockingQueue实现的队列中的锁是分离的,即生产用的是putLock,消费是takeLock

  2. 在生产或消费时操作不同:ArrayBlockingQueue实现的队列中在生产和消费的时候,是直接将枚举对象插入或移除的;LinkedBlockingQueue实现的队列中在生产和消费的时候,需要把枚举对象转换为Node<E>进行插入或移除,会影响性能。

  3. 队列大小初始化方式不同:ArrayBlockingQueue实现的队列中必须指定队列的大小;LinkedBlockingQueue实现的队列中可以不指定队列的大小,但是默认是Integer.MAX_VALUE

  4. 数据结构不同:ArrayBlockingQueue 数据存储容器是采用数组存储的;而 LinkedBlockingQueue 采用的是 Node 节点存储的。

注意:

1、在使用LinkedBlockingQueue时,若用默认大小且当生产速度大于消费速度时候,有可能会内存溢出。

2、在使用ArrayBlockingQueue和LinkedBlockingQueue分别对一百万个简单字符做入队操作时;LinkedBlockingQueue的消耗是ArrayBlockingQueue消耗的10倍左右。

7、在 Queue 中 poll()和 remove()有什么区别?

相同点:都是返回第一个元素,并在队列中删除返回的对象。

不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。

8、Stack和Queue的区别?

(1)栈和队列两者都被用来预存储数据。

(2)队列允许先进先出(FIFO)检索元素,但并非总是这样。Deque接口允许从两端检索元素。栈是后进先出(LIFO)进行检索。

(3)Stack是一个扩展自Vector的类,而Queue是一个接口。

上一篇:从零开发Java入门项目--十天掌握
下一篇:没有了
网友评论