Difference between add() and offer() methods of Queue interface - java

I was going though FIFO implementation in Java and came across this java.util.Queue interface. Dequeue implements it which in turn is implemented by Linked List.
I wrote the following code
public class FIFOTest {
public static void main(String args[]){
Queue<String> myQueue = new LinkedList<String>();
myQueue.add("US");
myQueue.offer("Canada");
for(String element : myQueue){
System.out.println("Element : " + element);
}
}
}
Both seem to do the same thing. Add data to the head of the queue. What is the difference between these two methods? Any special cases in which either would be more beneficial than other?

LinkedList#offer(E) is implemented as
public boolean offer(E e) {
return add(e);
}
In this case, they are the same thing. They are just needed to satisfy the interfaces. LinkedList implements Deque and List. The LinkedList#add(E) method will not throw an Exception as it will always take more elements, but in another Queue implementation that has limited capacity or takes only certain kinds of elements, add(E) might throw an exception while offer(E) will simply return false.

According to the docs the main difference is that when the operation fails, one (add) throws an exception and the other (offer) returns a special value (false):
Each of these methods exists in two forms: one throws an exception if the operation fails, the other returns a special value (either null or false, depending on the operation). The latter form of the insert operation is designed specifically for use with capacity-restricted Queue implementations; in most implementations, insert operations cannot fail.

What is the difference between these two methods?
Queue.add - throws an exception if the operation fails,
Queue.offer- returns a special value (either null or false, depending on the operation).
Any special cases in which either would be more beneficial than other?
According to docs, The Queue.offer form of the insert operation is designed specifically for
use with capacity-restricted Queue implementations; in most
implementations, insert operations cannot fail.
For details, read this docs.

add() comes from Collection Interface.
offer() comes from Queue Interface.
The Documentation of offer() method of Queue says
Inserts the specified element into this queue if it is possible to do
so immediately without violating capacity restrictions.
When using a capacity-restricted queue, this method is generally
preferable to {#link #add}, which can fail to insert an element only
by throwing an exception.
The Documentation of add() method of Queue says
Inserts the specified element into this queue if it is possible to do so
immediately without violating capacity restrictions, returning
<tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
if no space is currently available.

Related

The add(E e) method in Collection<E>&Queue<E>&BlockingQueue<E> interfaces

Question 1:
When reading JDK source codes I found that method boolean add(E e); defined in interface Collection<E>&Queue<E>&BlockingQueue<E> .
I cannot understand this. In my understanding if a super interface has defined a method, then a sub interface extending this super interface need not to define this method again.
So why has this method been defined three times?
Question 2:
Also I noticed that unlike the boolean add(E e); method which has been claimed in interface Queue<E> and then re-claimed in interface BlockingQueue<E>, the E poll(); method has been only claimed in interface Queue<E> and has not been re-claimed in interface BlockingQueue<E>.
So why are they treated differently?
Question 1: When reading JDK source codes I found boolean add(E e); defined in interface Collection&Queue&BlockingQueue .
I cannot understand this. In my understanding if a super interface has defined a method, then a sub interface extending this super interface need not to define this method again.
Yes, you don't need to redefine it. I'd guess it's probable because you'd need to repeat the declaration in order to add new JavaDoc comments, i.e. each of the interfaces has a specific description of what add(E) etc. do.
Question 2: also I noticed that unlike the boolean add(E e); method which has been claimed in interface Queue and then re-claimed in interface BlockingQueue, the E poll(); method has been only claimed in interface Queue and has not been re-claimed in interface BlockingQueue.
So why they are treated differently?
It's probably the same as above. poll(E) works the same way for general queues and blocking ones, hence no need for a different documentation.
The difference here is only on the documentation. The E poll() method signature was not mentioned in the BlockingQueue because the contract is the same for both Queue and BlockingQueue and the documentation for both explains the behaviour of the 2 data structure to be the same.
If you look at the documentation of Queue.add() and BlockingQueue.add(), you will see an additional sentence added on BlockingQueue.add() method.
Queue.add():
Inserts the specified element into this queue if it is possible to do
so immediately without violating capacity restrictions, returning true
upon success and throwing an IllegalStateException if no space is
currently available.
BlockingQueue.add():
Inserts the specified element into this queue if it is possible to do
so immediately without violating capacity restrictions, returning true
upon success and throwing an IllegalStateException if no space is
currently available. When using a capacity-restricted queue, it is
generally preferable to use offer.
This is to help developers when using the relevant object.
Technically, the add() method are the same so BlockingQueue never needed to explicitly specify that method signature.
I believe this is more to do with defining the behavior of what is expected from the method to behave. Technically, there is no need to defined add in the Queue or Blocking Queue but since the behaviour of add can be different depending on whether Collection is a Set or Queue, it's much better to re-define it so that people can understand what exactly is expected from Queue add method.
So, as long as behavior is not supposed to change or enhance, there is no need to declare the method in sub-interface but if you expect the behavior to be specific than you should go ahead and re-declare it.

Insertion on a Deque in Java

I would like to know what this tutorial means when it refers to the following bit of explanation. In particular the part which I highlighted in bold.
Insert
The addfirst and offerFirst methods insert elements at the beginning
of the Deque instance. The methods addLast and offerLast insert
elements at the end of the Deque instance. When the capacity of the
Deque instance is restricted, the preferred methods are offerFirst and
offerLast because addFirst might fail to throw an exception if it is
full.
Why would offerFirst be preferred?
Why would addFirst fail to throw an exception if it is full? Should not it be better if it guaranteed to throw an exception in those circumstances?
I think both methods are legitimate (though the offerXXX methods are more likely to be used in bounded dequeues).
If your code assumes that there's available space in the queue, and this assumption is critical to the correctness of the code, use addFirst/addLast. The runtime exception being thrown (IllegalStateException) is perfectly suitable for this bug scenario.
If, on the other hand, a full queue is a normal scenario, don't deal with it using exceptions. Use offerFirst/offerLast, and check the returned value.
OfferFirst is the prefereable methods if there is a risk the deque will reach capacity. If it has reached capacity addFirst will throw an exception, where as offerFirst returns a boolean (true/false) value to indicate if the add was successful. offerFirst Inserts the specified element at the front of this deque unless it would violate capacity restrictions. When using a capacity-restricted deque, this method is generally preferable to the addFirst(E) method, which can fail to insert an element only by throwing an exception.
Why would be that when using the restricted version you would not want an exception thrown when adding the element fails. This is because you would expect some failures which is why you are offering to add instead of insisting to add.
It means that the offerXXX methods return boolean, and the addXXX methods don't.
So it is recommending that you use offerXXX and check the boolean for success, rather than expecting an exception to be thrown from either method.
It's very badly worded. And so is the Javadoc.
According to Docs:
offerFirst:
Inserts the specified element at the front of this deque unless it would violate capacity restrictions. When using a capacity-restricted deque, this method is generally preferable to the addFirst(E) method, which can fail to insert an element only by throwing an exception.
Which means if you use addFirst with a capacity restricted deque, it may throw an exception, but using offerFirst won't throw any exception.
offerLast
Inserts the specified element at the end of this deque unless it would violate capacity restrictions. When using a capacity-restricted deque, this method is generally preferable to the addLast(E) method, which can fail to insert an element only by throwing an exception.
Similarly if you use addLast with a capacity restricted deque, it may throw an exception, but using offerLast won't throw any exception.

Inconsistency in Java Collection APIs

First of all, I am unable to find an interface for Stack data structure. It exists, but the one I find extends a Vector which I would try to avoid using. So, if you really need a stack, would you recommend me implementing my own stack class that has-a a ArrayDeque internally or would you recommend me using the Stack class that extends the Vector? I am very disappointed that a good Stack interface is non-existent in Java.
Secondly, Queue provides, add(e), remove() and element() methods. On top of that, they also provide offer(e), poll() and peek() methods. The former throws exception, while the latter returns true or false or null. Which one would you use if the Queue you want to use is for a non-concurrent case?
To answer your first "question:" Is there a drop-in replacement for Java Stack that is not synchronized?
And the second question: (I hate to have to say it, but) RTFD. Seriously.
public interface Queue<E> extends Collection<E>
... Each of these methods exists in two forms: one throws an exception if the operation fails, the other returns a special value (either null or false, depending on the operation). The latter form of the insert operation is designed specifically for use with capacity-restricted Queue implementations; in most implementations, insert operations cannot fail.
http://download.oracle.com/javase/7/docs/api/java/util/Queue.html
Neither set of methods has anything to do with concurrency. They simply allow you to choose between two programming styles (and hopefully, you're consistent!): do you want to have to check return values, or catch exceptions?
Deque<E> Q = new LinkedList<E>();
Q.add(e);
Q.remove();
Q.element();
Deque<E> S = new LinkedList<E>();
S.push(e);
S.pop();
S.peek();
I think I would rather use these methods in the common scenarios.
And when I have to worry about the success of the operation at runtime (example, concurrent case), I will go for the offer(E e, TimeUnit timeout) and poll(TimeUnit timeout) usage.
Try the Apache Commons Collections API if the JDK collections API doesn't exactly meet your needs
From Apache ArrayStack documentation which seems to match your requirements:
An implementation of the Stack API that is based on an ArrayList instead of a Vector, so it is not synchronized to protect against multi-threaded access. The implementation is therefore operates faster in environments where you do not need to worry about multiple thread contention.

Thread-safety of BlockingQueue's drainTo() method

Documentation of BlockingQueue says bulk operations are not thread-safe, though it doesn't explicitly mention the method drainTo().
BlockingQueue implementations are
thread-safe. All queuing methods
achieve their effects atomically using
internal locks or other forms of
concurrency control. However, the bulk
Collection operations addAll,
containsAll, retainAll and removeAll
are not necessarily performed
atomically unless specified otherwise
in an implementation. So it is
possible, for example, for addAll(c)
to fail (throwing an exception) after
adding only some of the elements in c.
Documentation of drainTo() method specifies that the collection, to which the elements of BlockingQueue are drained to, cannot be modified in thread-safe fashion. But, it doesn't mention anything about drainTo() operation being thread-safe.
Removes all available elements from
this queue and adds them to the given
collection. This operation may be more
efficient than repeatedly polling this
queue. A failure encountered while
attempting to add elements to
collection c may result in elements
being in neither, either or both
collections when the associated
exception is thrown. Attempts to drain
a queue to itself result in
IllegalArgumentException. Further, the
behavior of this operation is
undefined if the specified collection
is modified while the operation is in
progress.
So, is drainTo() method thread-safe? In other words, if one thread has invoked drainTo() method on a blocking queue and other one is calling add() or put() on the same queue, is the queue's state consistent at the end of both the operations?
I think you are confusing the terms "thread-safe" and "atomic". They do not mean the same thing. A method can be thread-safe without being atomic, and can be atomic (for a single thread) without being thread-safe.
Thread-safe is a rubbery term that is hard to define without being circular. According to Goetz, a good working model is that a method is thread-safe if it is "as correct" when used in a multi-threaded context as it is run in a single-threaded context. The rubberyness is in the fact that correctness is subjective unless you have a formal specification to measure against.
By contrast, atomic is easy to define. It simply means that the operation either happens completely or it doesn't happen at all.
So the answer to your question is that drainTo() is thread-safe, but not atomic. It is not atomic because it could throw an exception half way through draining. However, modulo that, the queue will still be in a consistent state, whether or not other threads were doing things to the queue at the same time.
(It is implicit in the above discussion that the specific implementation of the BlockingQueue interface implements the interface correctly. If it doesn't, all bets are off.)
drainTo() is thread safe in the sense that any operation on the queue that happens at the same time will not change the result nor will it corrupt the state of the queue. Otherwise, the method would be pretty pointless.
You could run into problems if the target collection (the one to which the results are added) does something "clever". But since you usually drain the queue to a collection to which only a single thread has access, it's more of a theoretical problem.
stumbled upon this question and felt like adding an implementation info.
From Java 8 source of PriorityBlockingQueue :
/**
* #throws UnsupportedOperationException {#inheritDoc}
* #throws ClassCastException {#inheritDoc}
* #throws NullPointerException {#inheritDoc}
* #throws IllegalArgumentException {#inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
return 0;
final ReentrantLock lock = this.lock;
lock.lock();
try {
int n = Math.min(size, maxElements);
for (int i = 0; i < n; i++) {
c.add((E) queue[0]); // In this order, in case add() throws.
dequeue();
}
return n;
} finally {
lock.unlock();
}
}
You can see that a ReentrantLock is used to lock the critical section. The methods poll() and offer() are also using the same lock. So the BlockingQueue implementation in this case of PriorityBlockingQueue is indeed Blocking!

What is the difference between the add and offer methods in a Queue in Java?

Take the PriorityQueue for example http://java.sun.com/j2se/1.5.0/docs/api/java/util/PriorityQueue.html#offer(E)
Can anyone give me an example of a Queue where the add and offer methods are different?
According to the Collection doc, the add method will often seek to ensure that an element exists within the Collection rather than adding duplicates. So my question is, what is the difference between the add and offer methods?
Is it that the offer method will add duplicates regardless? (I doubt that it is because if a Collection should only have distinct elements this would circumvent that).
EDIT:
In a PriorityQueue the add and offer methods are the same method (see my answer below). Can anyone give me an example of a class where the add and offer methods are different?
I guess the difference is in the contract, that when element can not be added to collection the add method throws an exception and offer doesn't.
From: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collection.html#add%28E%29
If a collection refuses to add a
particular element for any reason
other than that it already contains
the element, it must throw an
exception (rather than returning
false). This preserves the invariant
that a collection always contains the
specified element after this call
returns.
From: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Queue.html#offer%28E%29
Inserts the specified element into
this queue, if possible. When using
queues that may impose insertion
restrictions (for example capacity
bounds), method offer is generally
preferable to method
Collection.add(E), which can fail to
insert an element only by throwing an
exception.
The short answer: it depends on the concrete implementation.
If your queue has a max capacity limit, there actually is a difference.
Case #1 (no max capacity limit) applied:
There is no difference like the implementation of PriorityQueue:
public boolean add(E e) {
return offer(e);
}
Case #2 (max capacity limit) applied:
There actually is a difference like the implementation of ArrayBlockingQueue which extends AbstractQueue :
// ArrayBlockingQueue which extends AbstractQueue
public boolean add(E e) {
return super.add(e);
}
// AbstractQueue
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
offer: if the queue is full, return false and will not throw an exception
add: if the queue is full, throw an exception
The difference is following:
offer method - tries to add an element to a queue, and returns false if the element can't be added (like in case when a queue is full), or true if the element was added, and doesn't throw any specific exception.
add method - tries to add an element to a queue, returns true if the element was added, or throws an IllegalStateException if no space is currently available.
The difference between offer and add is explained by these two excerpts from the javadocs:
From the Collection interface:
If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an exception (rather than returning false). This preserves the invariant that a collection always contains the specified element after this call returns.
From the Queue interface
When using queues that may impose insertion restrictions (for example capacity bounds), method offer is generally preferable to method Collection.add(E), which can fail to insert an element only by throwing an exception.
PriorityQueue is a Queue implementation that does not impose any insertion restrictions. Therefore the add and offer methods have the same semantics.
By contrast, ArrayBlockingQueue is an implementation in which offer and add behave differently, depending on how the queue was instantiated.
The Queue interface specifies that add() will throw an IllegalStateException if no space is currently available (and otherwise return true) while offer() will return false if the element couldn't be inserted due to capacity restrictions.
The reason they are the same in a PriorityQueue is that this queue is specified to be unbounded, i.e. there are no capacity restrictions. In the case of no capacity restrictions, the contracts of add() and offer() display the same behaviour.
from the source code in jdk 7 as follow:
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
we can easily know that the add function will return true when successfully add a new element into the queue, but throw a exception when failed .
I will write the java contract example code for the offer method and the add method showing how they differ.
BlockingQueue<String> queue = new ArrayBlockingQueue<>(2);
queue.add("TestQuue1"); // will return true
queue.add("TestQuue2"); // will return true
queue.add("TestQuue3"); // will throw "java.lang.IllegalStateException: Queue full
BlockingQueue<String> queue = new ArrayBlockingQueue<>(2);
queue.offer("TestQuue1"); // will return true
queue.offer("TestQuue2"); // will return true
queue.offer("TestQuue3"); // will return false and will not throw any exception
Source: http://docs.oracle.com/javase/6/docs/api/java/util/Queue.html
The offer method inserts an element if possible, otherwise returning false. This differs from the Collection.add method, which can fail to add an element only by throwing an unchecked exception. The offer method is designed for use when failure is a normal, rather than exceptional occurrence, for example, in fixed-capacity (or "bounded") queues.
offer method throws true or false, if addition is done
add method throws an exception when no addition possible in queue

Categories