Comment obtenir un PriorityQueue
tri sur ce que je veux qu'il trie?
De plus, y a-t-il une différence entre les méthodes offer
et add
?
la source
Comment obtenir un PriorityQueue
tri sur ce que je veux qu'il trie?
De plus, y a-t-il une différence entre les méthodes offer
et add
?
Utilisez la surcharge du constructeur qui prend un Comparator<? super E> comparator
et passez dans un comparateur qui compare de la manière appropriée pour votre ordre de tri. Si vous donnez un exemple de la façon dont vous souhaitez trier, nous pouvons fournir un exemple de code pour implémenter le comparateur si vous n'êtes pas sûr. (C'est assez simple cependant.)
Comme cela a été dit ailleurs: offer
et ne add
sont que des implémentations de méthodes d'interface différentes. Dans la source JDK que j'ai, les add
appels offer
. Bien add
que le offer
comportement soit potentiellement différent en général en raison de la possibilité offer
d'indiquer que la valeur ne peut pas être ajoutée en raison de limitations de taille, cette différence n'est pas pertinente et n'est pas limitée PriorityQueue
.
Voici un exemple de tri de file d'attente prioritaire par longueur de chaîne:
// Test.java
import java.util.Comparator;
import java.util.PriorityQueue;
public class Test {
public static void main(String[] args) {
Comparator<String> comparator = new StringLengthComparator();
PriorityQueue<String> queue = new PriorityQueue<String>(10, comparator);
queue.add("short");
queue.add("very long indeed");
queue.add("medium");
while (queue.size() != 0) {
System.out.println(queue.remove());
}
}
}
// StringLengthComparator.java
import java.util.Comparator;
public class StringLengthComparator implements Comparator<String> {
@Override
public int compare(String x, String y) {
// Assume neither string is null. Real code should
// probably be more robust
// You could also just return x.length() - y.length(),
// which would be more efficient.
if (x.length() < y.length()) {
return -1;
}
if (x.length() > y.length()) {
return 1;
}
return 0;
}
}
Voici la sortie:
court
moyen
très long en effet
compare
mise en œuvre ne devrait-elle pas être justereturn x.length() - y.length()
? (Évite la prédiction de branche)add()
pour l'opération d'ajout, celaremove()
semble raisonnable; si j'utilisaisoffer()
j'utiliserais probablementpoll()
... mais c'est juste une préférence personnelle.Solution Java 8
Nous pouvons utiliser
lambda expression
oumethod reference
introduire dans Java 8. Dans le cas où nous avons des valeurs de chaîne stockées dans la file d'attente prioritaire (ayant une capacité 5), nous pouvons fournir un comparateur en ligne (basé sur la longueur de la chaîne):Utilisation de l'expression lambda
Utilisation de la référence de méthode
Ensuite, nous pouvons utiliser l'un d'eux comme:
Cela imprimera:
Pour inverser l'ordre (pour le changer en file d'attente prioritaire), changez simplement l'ordre dans le comparateur en ligne ou utilisez
reversed
comme:Nous pouvons également utiliser
Collections.reverseOrder
:Nous pouvons donc voir qu'il
Collections.reverseOrder
est surchargé pour prendre un comparateur qui peut être utile pour les objets personnalisés. Lereversed
utilise en faitCollections.reverseOrder
:offer () vs add ()
Selon le doc
Lorsque vous utilisez une file d'attente à capacité limitée, offer () est généralement préférable d'ajouter (), qui ne peut pas insérer un élément uniquement en lançant une exception. Et PriorityQueue est une file d'attente prioritaire illimitée basée sur un segment de priorité.
la source
5
indique la capacité de démarrage de la file d'attente?Passez juste approprié
Comparator
au constructeur :La seule différence entre
offer
etadd
est l'interface à laquelle ils appartiennent.offer
appartient àQueue<E>
, alors que l'add
on voit à l'origine dans l'Collection<E>
interface. En dehors de cela, les deux méthodes font exactement la même chose - insérez l'élément spécifié dans la file d'attente prioritaire.la source
de API Queue :
la source
pas différent, comme le déclare javadoc:
la source
Juste pour répondre à la question
add()
vsoffer()
(puisque l'autre est parfaitement répondu imo, et cela pourrait ne pas l'être):Selon JavaDoc sur l' interface de file d' attente , "La méthode offre insère un élément si possible, sinon renvoie false. Cela diffère de la méthode Collection.add, qui ne peut pas ajouter un élément uniquement en lançant une exception non vérifiée. La méthode offre est conçue pour à utiliser lorsque l'échec est une occurrence normale, plutôt qu'exceptionnelle, par exemple, dans les files d'attente à capacité fixe (ou "délimitée"). "
Cela signifie que si vous pouvez ajouter l'élément (ce qui devrait toujours être le cas dans un PriorityQueue), ils fonctionnent exactement de la même manière. Mais si vous ne pouvez pas ajouter l'élément, vous
offer()
obtiendrez unfalse
retour agréable et joli , tout enadd()
lançant une méchante exception non vérifiée que vous ne voulez pas dans votre code. Si l'échec de l'ajout signifie que le code fonctionne comme prévu et / ou que c'est quelque chose que vous vérifierez normalement, utilisezoffer()
. Si l'échec de l'ajout signifie que quelque chose est cassé, utilisezadd()
et gérez l'exception résultante levée conformément aux spécifications de l'interface Collection .Ils sont tous deux implémentés de cette manière pour remplir le contrat sur l'interface de file d'attente qui spécifie les
offer()
échecs en renvoyant unfalse
( méthode préférée dans les files d'attente à capacité limitée ) et également maintenir le contrat sur l'interface de collecte qui spécifieadd()
toujours les échecs en lançant une exception .Quoi qu'il en soit, j'espère que cela clarifie au moins cette partie de la question.
la source
Ici, nous pouvons définir un comparateur défini par l'utilisateur:
Différence entre l'offre et les méthodes d'ajout: lien
la source
Passez-le a
Comparator
. Remplissez votre type souhaité à la place deT
Utilisation de lambdas (Java 8+):
De façon classique, en utilisant une classe anonyme:
Pour trier dans l'ordre inverse, échangez simplement e1, e2.
la source
Je me posais également des questions sur la commande d'impression. Considérez ce cas, par exemple:
Pour une file d'attente prioritaire:
Ce code:
peut imprimer différemment de:
J'ai trouvé la réponse d'une discussion sur un autre forum , où un utilisateur a dit: "les méthodes offer () / add () n'insèrent que l'élément dans la file d'attente. Si vous voulez un ordre prévisible, vous devez utiliser peek / poll qui renvoie la tête de la file d'attente. "
la source
Comme alternative à l'utilisation
Comparator
, vous pouvez également avoir la classe que vous utilisez dans votrePriorityQueue
implémentationComparable
(et remplacer en conséquence lacompareTo
méthode).Notez qu'il est généralement préférable d'utiliser uniquement
Comparable
au lieu deComparator
si cet ordre est l'ordre intuitif de l'objet - si, par exemple, vous avez un cas d'utilisation pour trier lesPerson
objets par âge, il est probablement préférable de simplement utiliser à laComparator
place.Production:
la source
La file d'attente prioritaire a une priorité assignée à chaque élément. L'élément avec la priorité la plus élevée apparaît en haut de la file d'attente. Maintenant, cela dépend de vous de la façon dont vous souhaitez attribuer la priorité à chacun des éléments. Sinon, Java le fera par défaut. L'élément avec la valeur la plus faible se voit attribuer la priorité la plus élevée et est donc supprimé en premier de la file d'attente. S'il y a plusieurs éléments avec la même priorité la plus élevée, le lien est rompu arbitrairement. Vous pouvez également spécifier une commande à l'aide de Comparator dans le constructeur
PriorityQueue(initialCapacity, comparator)
Exemple de code:
Production:
Sinon, vous pouvez également définir un comparateur personnalisé:
la source
Voici l'exemple simple que vous pouvez utiliser pour l'apprentissage initial:
la source