在 Java 中,Queue 中的 add 和 offer 方法之间有什么区别?

PriorityQueue为例

谁能给我一个 Queue的例子,其中的 addoffer的方法是不同的?

根据 Collection文档,add方法通常会寻求确保一个元素存在于 Collection中,而不是添加重复的元素。所以我的问题是,addoffer方法之间的区别是什么?

是不是 offer方法无论如何都会添加重复项?(我怀疑这是因为如果一个 Collection应该只有不同的元素,这将规避这一点)。

编辑: 在 PriorityQueue中,addoffer方法是相同的方法(见下面我的答案)。有没有人能给我一个类的例子,其中的 addoffer方法是不同的?

119710 次浏览

实施 PriorityQueue.add没有区别:

public boolean add(E e) {
return offer(e);
}

对于 AbstractQueue来说,实际上是有区别的:

public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}

我猜不同之处在于契约,当元素不能添加到集合中时,add方法抛出异常,而 offer不会。

发信人: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collection.html#add%28E%29

如果集合拒绝添加 任何原因的特定元素 除了它已经包含的 元素,它 必须扔和 异常(而不是返回 这保留了不变量 集合始终包含 调用后指定的元素 报税表。

发信人: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Queue.html#offer%28E%29

将指定的元素插入 如果可能的话,这个队列。当使用 可能强制插入的队列 限制(例如容量) 界限) ,方法提供一般是 比方法更好 Add (E) ,它可能会失败 仅通过引发 例外。

offeradd之间的区别可以从 javadocs 中的以下两段摘录中得到解释:

Collection接口:

如果一个集合拒绝 add某个特定元素的原因不是因为它已经包含了该元素,那么它必须抛出一个异常(而不是返回 false)。这保留了集合在此调用返回后始终包含指定元素的不变量。

Queue接口

当使用可能施加插入限制(例如容量界限)的队列时,方法 offer通常优于方法 Collection.add(E),后者只能通过引发异常而无法插入元素。

PriorityQueue是一个 Queue实现,它不施加任何插入限制。因此,addoffer方法具有相同的语义。

相比之下,ArrayBlockingQueue是一种实现,其中 offeradd的行为不同,这取决于队列的实例化方式。

资料来源: http://docs.oracle.com/javase/6/docs/api/java/util/Queue.html

Offer 方法在可能的情况下插入一个元素,否则返回 false。这与 Collection.add 方法不同,Collection.add 方法只能通过引发未检查的异常而无法添加元素。Offer 方法的设计目的是为了在例如固定容量(或“有界”)队列中发生正常故障而不是异常故障时使用。

来自 jdk 7中的源代码,如下所示:

public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}

我们可以很容易地知道,add 函数在成功地向队列中添加新元素时将返回 true,但在失败时抛出异常。

Queue接口指定,如果当前没有可用空间(或返回 true) ,add()将抛出 IllegalStateException,而如果由于容量限制无法插入元素,offer()将返回 false

它们在 PriorityQueue中相同的原因是这个队列被指定为无界的,也就是说没有容量限制。在没有容量限制的情况下,add()offer()的合同表现出同样的行为。

我将为 offer 方法和 add 方法编写 java 契约示例代码,展示它们之间的区别。

BlockingQueue<String> queue = new ArrayBlockingQueue<>(2);
queue.add("TestQuue1");
queue.add("TestQuue2");
queue.add("TestQuue3");  // will throw "java.lang.IllegalStateException: Queue full


BlockingQueue<String> queue = new ArrayBlockingQueue<>(2);
queue.offer("TestQuue1");
queue.offer("TestQuue2");
queue.offer("TestQuue3"); // will not throw any exception

区别在于:

  • Offer method-尝试将一个元素添加到队列中,如果不能添加该元素,则返回 错误(如果队列已满) ,如果添加了该元素,则返回 真实,并且不引发任何特定异常。

  • Add method-尝试将一个元素添加到队列中,如果添加了该元素,则返回 真实,如果当前没有可用空间,则抛出 IllegalStateException。

Offer 方法抛出 true 或 false,如果添加完成

当队列中不可能添加内容时,add 方法引发异常