¿Cómo obtengo un PriorityQueue
orden sobre lo que quiero que clasifique?
Además, ¿hay alguna diferencia entre los métodos offer
y add
?
fuente
¿Cómo obtengo un PriorityQueue
orden sobre lo que quiero que clasifique?
Además, ¿hay alguna diferencia entre los métodos offer
y add
?
Use la sobrecarga del constructor que toma ay Comparator<? super E> comparator
pase en un comparador que se compara de la manera apropiada para su orden de clasificación. Si da un ejemplo de cómo desea ordenar, podemos proporcionar un código de muestra para implementar el comparador si no está seguro. (Sin embargo, es bastante sencillo).
Como se ha dicho en otra parte: offer
y add
son solo implementaciones de métodos de interfaz diferentes. En la fuente JDK que tengo, add
llamadas offer
. Aunque add
y offer
tienen un comportamiento potencialmente diferente en general debido a la capacidad de offer
indicar que el valor no se puede agregar debido a limitaciones de tamaño, esta diferencia es irrelevante en lo PriorityQueue
que no tiene límites.
Aquí hay un ejemplo de una clasificación de cola prioritaria por longitud de cadena:
// 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;
}
}
Aquí está la salida:
corto
medio
muy largo de hecho
compare
implementación soloreturn x.length() - y.length()
? (Evita la predicción de rama)add()
para la operación de agregar, entonces seremove()
siente razonable; si estuviera usandooffer()
probablemente usaríapoll()
... pero eso es solo una preferencia personal.Solución Java 8
Podemos usar
lambda expression
omethod reference
introducir en Java 8. En caso de que tengamos algunos valores de String almacenados en la Cola de prioridad (con capacidad 5), podemos proporcionar un comparador en línea (basado en la longitud de String):Usando la expresión lambda
Usando referencia de método
Entonces podemos usar cualquiera de ellos como:
Esto imprimirá:
Para invertir el orden (para cambiarlo a la cola de máxima prioridad) simplemente cambie el orden en el comparador en línea o úselo
reversed
como:También podemos usar
Collections.reverseOrder
:Entonces podemos ver que
Collections.reverseOrder
está sobrecargado para tomar el comparador que puede ser útil para objetos personalizados. Elreversed
realmente utilizaCollections.reverseOrder
:oferta () vs agregar ()
Según el documento
Cuando se usa una cola de capacidad restringida, generalmente es preferible ofrecer () a add (), que puede fallar al insertar un elemento solo lanzando una excepción. Y PriorityQueue es una cola de prioridad ilimitada basada en un montón de prioridad.
fuente
5
indica la capacidad de inicio de la cola?Simplemente pase apropiado
Comparator
al constructor :La única diferencia entre
offer
yadd
es la interfaz a la que pertenecen.offer
pertenece aQueue<E>
, mientrasadd
que originalmente se ve en laCollection<E>
interfaz. Aparte de eso, ambos métodos hacen exactamente lo mismo: insertar el elemento especificado en la cola de prioridad.fuente
de la API de cola :
fuente
no es diferente, como declaramos en javadoc:
fuente
Solo para responder la pregunta
add()
vsoffer()
(ya que la otra está perfectamente respondida imo, y esto podría no ser así):De acuerdo con JavaDoc en la cola de la interfaz , "El método de oferta inserta un elemento si es posible, de lo contrario devuelve falso. Esto difiere del método Collection.add, que puede fallar al agregar un elemento solo lanzando una excepción no verificada. El método de oferta está diseñado para se usa cuando la falla es normal, en lugar de excepcional, por ejemplo, en colas de capacidad fija (o "limitada").
Eso significa que si puede agregar el elemento (que siempre debería ser el caso en un PriorityQueue), funcionan exactamente igual. Pero si no puede agregar el elemento,
offer()
le dará unfalse
retorno agradable y bonito , mientrasadd()
arroja una desagradable excepción no marcada que no desea en su código. Si la falta de agregar significa que el código funciona según lo previsto y / o es algo que verificará normalmente, úselooffer()
. Si la falta de agregar significa que algo está roto, useadd()
y maneje la excepción resultante lanzada de acuerdo con las especificaciones de la interfaz de la Colección .Ambos se implementan de esta manera para completar el contrato en la interfaz de cola que especifica
offer()
fallas al devolver unfalse
( método preferido en colas de capacidad restringida ) y también mantener el contrato en la interfaz de colección que especificaadd()
siempre falla lanzando una excepción .De todos modos, espero que eso aclare al menos esa parte de la pregunta.
fuente
Aquí, podemos definir un comparador definido por el usuario:
Diferencia entre la oferta y los métodos de agregar: enlace
fuente
Pásalo a
Comparator
. Complete el tipo deseado en lugar deT
Usando lambdas (Java 8+):
Manera clásica, usando clase anónima:
Para ordenar en orden inverso, simplemente cambie e1, e2.
fuente
También me preguntaba sobre la orden de impresión. Considere este caso, por ejemplo:
Para una cola prioritaria:
Este código:
puede imprimir de manera diferente a:
Encontré la respuesta de una discusión en otro foro , donde un usuario dijo: "los métodos offer () / add () solo insertan el elemento en la cola. Si desea un orden predecible, debe usar peek / poll que devuelve el encabezado de la cola ".
fuente
Como alternativa al uso
Comparator
, también puede tener la clase que está usando en suPriorityQueue
implementoComparable
(y anular la correspondientecompareTo
método ).Tenga en cuenta que generalmente es mejor usar solo en
Comparable
lugar deComparator
si ese orden es el ordenamiento intuitivo del objeto; si, por ejemplo, tiene un caso de uso para ordenarPerson
objetos por edad, probablemente sea mejor usarloComparator
en su lugar.Salida:
fuente
La cola de prioridad tiene alguna prioridad asignada a cada elemento. El elemento con la prioridad más alta aparece en la parte superior de la cola. Ahora, depende de usted cómo desea asignar la prioridad a cada uno de los elementos. Si no lo hace, Java lo hará de la manera predeterminada. Al elemento con el menor valor se le asigna la máxima prioridad y, por lo tanto, se elimina primero de la cola. Si hay varios elementos con la misma prioridad más alta, el empate se rompe arbitrariamente. También puede especificar un pedido usando Comparator en el constructor
PriorityQueue(initialCapacity, comparator)
Código de ejemplo:
Salida:
De lo contrario, también puede definir un comparador personalizado:
fuente
Aquí está el ejemplo simple que puede usar para el aprendizaje inicial:
fuente