Prenez le PriorityQueue
par exemple http://Java.Sun.com/j2se/1.5.0/docs/api/Java/util/PriorityQueue.html#offer (E)
Quelqu'un peut-il me donner un exemple de Queue
où add
et offer
les méthodes sont différentes?
Selon la Collection
doc, la méthode add
cherchera souvent à s'assurer qu'un élément existe dans la Collection
plutôt que d'ajouter des doublons. Ma question est donc la suivante: quelle est la différence entre les méthodes add
et offer
?
Est-ce que la méthode offer
ajoutera des doublons malgré tout? (Je doute que ce soit parce que si un Collection
ne devrait avoir que des éléments distincts, cela le contournerait).
EDIT: Dans un PriorityQueue
, les méthodes add
et offer
sont identiques (voir ma réponse ci-dessous). Quelqu'un peut-il me donner un exemple de classe où les méthodes add
et offer
sont différentes?
J'imagine que la différence réside dans le contrat: lorsque l'élément ne peut pas être ajouté à la collection, la méthode add
lève une exception et offer
ne le fait pas.
De: http://Java.Sun.com/j2se/1.5.0/docs/api/Java/util/Collection.html#add%28E%29
Si une collection refuse d'ajouter un élément particulier pour une raison autre que celle qui le contient déjà, elle doit renvoyer une exception (plutôt que de renvoyer false) . Cela préserve l'invariant qu'une collection contient toujours l'élément spécifié après le retour de cet appel.
De: http://Java.Sun.com/j2se/1.5.0/docs/api/Java/util/Queue.html#offer%28E%29
Insère l'élément spécifié dans cette file d'attente, si possible. Lorsque vous utilisez des files d'attente pouvant imposer des restrictions d'insertion (par exemple, des limites de capacité), l'offre méthode est généralement préférable à la méthode Collection.add (E), qui peut échouer lors de l'insertion d'un élément uniquement en lançant une exception.
Il n'y a pas de différence pour la mise en œuvre de PriorityQueue.add
:
public boolean add(E e) {
return offer(e);
}
Pour AbstractQueue
, il y a une différence:
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
La différence entre offer
et add
s'explique par ces deux extraits des javadocs:
Depuis l’interface Collection
:
Si une collection refuse de
add
un élément en particulier pour une raison autre que celle qui le contient déjà, elle doit lever une exception (plutôt que de renvoyer false). Cela préserve l'invariant qu'une collection contient toujours l'élément spécifié après le retour de cet appel.
Depuis l'interface Queue
Lorsque vous utilisez des files d'attente pouvant imposer des restrictions d'insertion (par exemple, des limites de capacité), la méthode
offer
est généralement préférable à la méthodeCollection.add(E)
, qui peut échouer lors de l'insertion d'un élément uniquement en lançant une exception.
PriorityQueue
est une implémentation de Queue
qui n'impose aucune restriction d'insertion. Par conséquent, les méthodes add
et offer
ont la même sémantique.
En revanche, ArrayBlockingQueue
est une implémentation dans laquelle offer
et add
se comportent différemment, en fonction de la manière dont la file d'attente a été instanciée.
à partir du code source dans jdk 7 comme suit:
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
nous pouvons facilement savoir que la fonction add retournera true si un nouvel élément est ajouté avec succès dans la file d'attente, mais émet une exception en cas d'échec.
La différence est la suivante:
offer methode - tente d'ajouter un élément à une file d'attente et renvoie false si l'élément ne peut pas être ajouté (comme dans le cas où une file d'attente est pleine), ou true si l'élément a été ajouté, et ne jette aucune exception spécifique.
add méthode - essaie d'ajouter un élément à une file d'attente, renvoie true si l'élément était ajouté ou lève une exception IllegalStateException si aucun espace n'est actuellement disponible.
L'interface Queue
indique que add()
lève un IllegalStateException
si aucun espace n'est actuellement disponible (sinon renvoie true
) tandis que offer()
retournera false
si l'élément n'a pas pu être inséré en raison de restrictions de capacité.
La raison pour laquelle ils sont identiques dans un PriorityQueue
est que cette file d'attente est définie comme étant non liée, c'est-à-dire qu'il n'y a pas de restriction de capacité. En l'absence de limitation de capacité, les contrats de add()
et offer()
affichent le même comportement.
J'écrirai le code d'exemple de contrat Java pour la méthode d'offre et la méthode d'ajout illustrant leurs différences.
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
Source: http://docs.Oracle.com/javase/6/docs/api/Java/util/Queue.html
La méthode offer insère un élément si possible, sinon retourne false. Cela diffère de la méthode Collection.add, qui peut ne pas réussir à ajouter un élément uniquement en lançant une exception non contrôlée. La méthode d'offre est conçue pour être utilisée lorsque la défaillance est un événement normal plutôt qu'exceptionnel, par exemple dans les files d'attente à capacité fixe (ou "liées").