JDK8源码详解-util篇-AbstractQueue

概述

功能:该类提供了Queue接口的基础框架

开始版本JDK 1.5

注意
1. 本类为抽象
2. 可以存放相同元素,但不能存放null
3. 数据结构:顺序队列、链队列
4. 本类不同于其他集合,本类有两组增删查的方法,分别是add/offer(增),element/peek(查首位元素),remove/poll(删),区别为前者遇见队列满、队列为空会抛异常,而后者则返回falsenullnull,不会抛出异常并可以用于判断
5. 本方法没有单独重写toString()方法,使用的是AbstractCollectiontoString()方法
6. 本方法及实现/继承的接口均没有重写hashCode()equals()方法,直接比较内容相同的两个不同队列返回结果为false,如需返回为true需重写这两个方法

常见队列具体实现类
1. PriorityQueue (优先级队列,不一定先进先出,与元素有关,非堵塞队列,非线程安全)
2. ConcurrentLinkedQueue (链队列,非堵塞,线程安全)
3. ArrayBlockingQueue (堵塞队列,线程安全)
4. LinkedBlockingQueue (链队列,堵塞队列,线程安全)
5. PriorityBlockingQueue (优先级队列,堵塞队列,线程安全)
6. DelayQueue (优先级队列,不一定先进先出,与元素有关,堵塞队列,线程安全,有延迟期)
7. SynchronousQueue (容量为0不储存元素,堵塞队列,线程安全)
8. LinkedBlockingDeque (链队列,堵塞队列,线程安全、双端)

实现接口java.util.Queue

继承类java.util.AbstractCollection

所在包java.util

类声明

public abstract class AbstractQueue<E> extends AbstractCollection<E> implements Queue<E> {}

框架图

image

方法

构造器

// 唯一构造器
protected AbstractQueue() {}

公有方法

01.新增元素 add(E e)

参数e —— 要新增的元素

注意:本方法先调用Queue接口的offer(E e)新增,新增失败(无空间)会返回false,此时本方法直接抛出IllegalStateException异常

// 源码
public boolean add(E e) {
    if (offer(e))
        return true;
    else
        throw new IllegalStateException("Queue full");
}
// 正常示例
@Test
void contextLoads() {
    // 需注意 PriorityQueue 和 ConcurrentLinkedQueue 是非堵塞队列,创建时设置了大小
    // 超过也仍然可以自带扩容存入,此处使用ArrayBlockingQueue,该队列时堵塞队列
    Queue arrayBlockingQueue = new ArrayBlockingQueue(2);
    arrayBlockingQueue.add(1);
    arrayBlockingQueue.add(0);
    arrayBlockingQueue.add(3);
    // java.lang.IllegalStateException: Queue full
    System.out.println(arrayBlockingQueue.element());
}

02.移除当前队首元素 remove()

注意:本方法先调用Queue接口的poll()移除,移除失败(队列为空)会返回null,此时本方法直接抛出NoSuchElementException异常

// 源码
public E remove() {
    E x = poll();
    if (x != null)
        return x;
    else
        throw new NoSuchElementException();
}
// 示例:队列为空 
@Test
void contextLoads() {
    Queue priorityQueue = new PriorityQueue(2);
    // null
    System.out.println(priorityQueue.poll());

    Queue priorityQueue1 = new PriorityQueue(2);
    // java.util.NoSuchElementException
    System.out.println(priorityQueue1.remove());
}
// 正常示例
@Test
void contextLoads() {
    // 需注意PriorityQueue是优先级队列,不一定是先进先出,此处使用ConcurrentLinkedQueue
    Queue concurrentLinkedQueue = new ConcurrentLinkedQueue();
    concurrentLinkedQueue.add(1);
    concurrentLinkedQueue.add(0);
    concurrentLinkedQueue.add(3);
    concurrentLinkedQueue.poll();
    // [0, 3]
    System.out.println(concurrentLinkedQueue);
}

03.查看当前队首元素 element()

注意:本方法先调用Queue接口的peek()查询,未查询到(队列为空)会返回null,此时本方法直接抛出NoSuchElementException异常

// 源码
public E element() {
    E x = peek();
    if (x != null)
        return x;
    else
        throw new NoSuchElementException();
}
// 示例:队列为空 
@Test
void contextLoads() {
    Queue priorityQueue = new PriorityQueue(2);
    // null
    System.out.println(priorityQueue.peek());

    Queue priorityQueue1 = new PriorityQueue(2);
    // java.util.NoSuchElementException
    System.out.println(priorityQueue1.element());
}
// 正常示例
@Test
void contextLoads() {
    // ConcurrentLinkedQueue:先进先出
    Queue concurrentLinkedQueue = new ConcurrentLinkedQueue();
    concurrentLinkedQueue.add(1);
    concurrentLinkedQueue.add(0);
    concurrentLinkedQueue.add(3);
    concurrentLinkedQueue.poll();
    // 此处元素1出队,下一个是0 【输出0】
    System.out.println(concurrentLinkedQueue.element());

    // 需注意PriorityQueue是优先级队列,不一定是先进先出
    PriorityQueue<Object> queue = new PriorityQueue<>();
    queue.add(1);
    queue.add(0);
    queue.add(3);
    queue.poll();
    // 此处元素0出队,按优先级下一个是0 【输出1】
    System.out.println(queue.element());
}

04.清空队列 clear()

说明:调用Queue接口的poll()一个个元素移除,根据返回值是否为null判断是否全部移除

// 源码
public void clear() {
    while (poll() != null)
        ;
}
// 示例
@Test
void contextLoads() {
    Queue priorityQueue = new PriorityQueue(2);
    priorityQueue.add(1);
    priorityQueue.add(2);
    // [1, 2]
    System.out.println(priorityQueue);
    priorityQueue.clear();
    // []
    System.out.println(priorityQueue);
}

05.将指定集合全部元素存入队列 addAll(Collection<? extends E> c)

参数c —— 要存入的集合

注意
1. 指定集合为null或就是此队列本身时会抛出异常
2. 本方法调用的是add(E e)方法不是offer(E e),对于堵塞队列,若队列已满会抛出异常
3. 若指定集合中有元素为null,调用本方法也会抛出异常
4. 需要在调用时校验指定集合的类型与队列是否一致,不一致且不能转换也会抛出异常

// 源码
public boolean addAll(Collection<? extends E> c) {
    if (c == null)
        throw new NullPointerException();
    if (c == this)
        throw new IllegalArgumentException();
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}
// 示例:类型不同 
@Test
void contextLoads() {
    Queue priorityQueue = new PriorityQueue(2);
    priorityQueue.add(1);
    priorityQueue.add(2);
    // [1, 2]
    System.out.println(priorityQueue);
    List list = new ArrayList();
    list.add("1");
    list.add("2");
    // [1, 2]
    System.out.println(list);
    // java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    priorityQueue.addAll(list);
    System.out.println(priorityQueue);
}
// 示例:集合存在null值
@Test
void contextLoads() {
    Queue priorityQueue = new PriorityQueue(2);
    priorityQueue.add(1);
    priorityQueue.add(2);
    // [1, 2]
    System.out.println(priorityQueue);
    List list = new ArrayList();
    list.add(1);
    list.add(2);
    list.add(null);
    list.add(3);
    // [1, 2, null, 3]
    System.out.println(list);
    // java.lang.NullPointerException
    priorityQueue.addAll(list);
    System.out.println(priorityQueue);
}
// 正常示例
@Test
void contextLoads() {
    Queue priorityQueue = new PriorityQueue(2);
    priorityQueue.add(1);
    priorityQueue.add(2);
    // [1, 2]
    System.out.println(priorityQueue);
    List list = new ArrayList();
    list.add(1);
    list.add(2);
    list.add(3);
    // [1, 2, 3]
    System.out.println(list);
    priorityQueue.addAll(list);
    // [1, 2, 1, 2, 3]
    System.out.println(priorityQueue);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值