阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

使用Queue

30次阅读
没有评论

共计 2434 个字符,预计需要花费 7 分钟才能阅读完成。

队列(Queue)是一种经常使用的集合。Queue实际上是实现了一个先进先出(FIFO:First In First Out)的有序表。它和 List 的区别在于,List可以在任意位置添加和删除元素,而 Queue 只有两个操作:

  • 把元素添加到队列末尾;
  • 从队列头部取出元素。

超市的收银台就是一个队列:

使用 Queue

在 Java 的标准库中,队列接口 Queue 定义了以下几个方法:

  • int size():获取队列长度;
  • boolean add(E)/boolean offer(E):添加元素到队尾;
  • E remove()/E poll():获取队首元素并从队列中删除;
  • E element()/E peek():获取队首元素但并不从队列中删除。

对于具体的实现类,有的 Queue 有最大队列长度限制,有的 Queue 没有。注意到添加、删除和获取队列元素总是有两个方法,这是因为在添加或获取元素失败时,这两个方法的行为是不同的。我们用一个表格总结如下:

throw Exception 返回 false 或 null
添加元素到队尾 add(E e) boolean offer(E e)
取队首元素并删除 E remove() E poll()
取队首元素但不删除 E element() E peek()

举个栗子,假设我们有一个队列,对它做一个添加操作,如果调用 add() 方法,当添加失败时(可能超过了队列的容量),它会抛出异常:

Queue<String> q = ...
try {q.add("Apple");
    System.out.println("添加成功");
} catch(IllegalStateException e) {System.out.println("添加失败");
}

如果我们调用 offer() 方法来添加元素,当添加失败时,它不会抛异常,而是返回false

Queue<String> q = ...
if (q.offer("Apple")) {System.out.println("添加成功");
} else {System.out.println("添加失败");
}

当我们需要从 Queue 中取出队首元素时,如果当前 Queue 是一个空队列,调用 remove() 方法,它会抛出异常:

Queue<String> q = ...
try {String s = q.remove();
    System.out.println("获取成功");
} catch(IllegalStateException e) {System.out.println("获取失败");
}

如果我们调用 poll() 方法来取出队首元素,当获取失败时,它不会抛异常,而是返回null

Queue<String> q = ...
String s = q.poll();
if (s != null) {System.out.println("获取成功");
} else {System.out.println("获取失败");
}

因此,两套方法可以根据需要来选择使用。

注意:不要把 null 添加到队列中,否则 poll() 方法返回 null 时,很难确定是取到了 null 元素还是队列为空。

接下来我们以 poll()peek()为例来说说“获取并删除”与“获取但不删除”的区别。对于 Queue 来说,每次调用poll(),都会获取队首元素,并且获取到的元素已经从队列中被删除了:

import java.util.LinkedList;
import java.util.Queue;

public class Main {public static void main(String[] args) {Queue<String> q = new LinkedList<>();
        // 添加 3 个元素到队列:
        q.offer("apple");
        q.offer("pear");
        q.offer("banana");
        // 从队列取出元素:
        System.out.println(q.poll()); // apple
        System.out.println(q.poll()); // pear
        System.out.println(q.poll()); // banana
        System.out.println(q.poll()); // null, 因为队列是空的
    }
}

如果用peek(),因为获取队首元素时,并不会从队列中删除这个元素,所以可以反复获取:

import java.util.LinkedList;
import java.util.Queue;

public class Main {public static void main(String[] args) {Queue<String> q = new LinkedList<>();
        // 添加 3 个元素到队列:
        q.offer("apple");
        q.offer("pear");
        q.offer("banana");
        // 队首永远都是 apple,因为 peek()不会删除它:
        System.out.println(q.peek()); // apple
        System.out.println(q.peek()); // apple
        System.out.println(q.peek()); // apple
    }
}

从上面的代码中,我们还可以发现,LinkedList即实现了 List 接口,又实现了 Queue 接口,但是,在使用的时候,如果我们把它当作 List,就获取 List 的引用,如果我们把它当作 Queue,就获取 Queue 的引用:

// 这是一个 List:
List<String> list = new LinkedList<>();
// 这是一个 Queue:
Queue<String> queue = new LinkedList<>();

始终按照面向抽象编程的原则编写代码,可以大大提高代码的质量。

小结

队列 Queue 实现了一个先进先出(FIFO)的数据结构:

  • 通过 add()/offer() 方法将元素添加到队尾;
  • 通过 remove()/poll() 从队首获取元素并删除;
  • 通过 element()/peek() 从队首获取元素但不删除。

要避免把 null 添加到队列。

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计2434字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中