Como faço PriorityQueue
para classificar o que eu quero?
Além disso, existe uma diferença entre os métodos offer
e add
?
fonte
Como faço PriorityQueue
para classificar o que eu quero?
Além disso, existe uma diferença entre os métodos offer
e add
?
Use a sobrecarga do construtor que recebe Comparator<? super E> comparator
e passa em um comparador que compara da maneira apropriada para sua ordem de classificação. Se você der um exemplo de como deseja classificar, podemos fornecer alguns exemplos de código para implementar o comparador, se você não tiver certeza. (É bastante simples.)
Como foi dito em outro lugar: offer
e add
são apenas implementações diferentes de métodos de interface. Na fonte JDK que tenho, add
chama offer
. Embora add
e offer
possua um comportamento potencialmente diferente em geral devido à capacidade de offer
indicar que o valor não pode ser adicionado devido a limitações de tamanho, essa diferença é irrelevante na PriorityQueue
qual é ilimitada.
Aqui está um exemplo de uma fila de prioridade que classifica pelo comprimento da string:
// 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;
}
}
Aqui está a saída:
baixo
médio
muito tempo mesmo
compare
implementação não deveria ser apenasreturn x.length() - y.length()
? (Predição ramo Evita)add()
a operação de adição, seráremove()
sensato; se eu estivesse usandooffer()
, provavelmente usariapoll()
... mas isso é apenas uma preferência pessoal.Solução Java 8
Podemos usar
lambda expression
oumethod reference
introduzir no Java 8. Caso tenhamos alguns valores de String armazenados na fila de prioridade (com capacidade 5), podemos fornecer um comparador em linha (com base no comprimento de String):Usando expressão lambda
Usando referência de método
Em seguida, podemos usar qualquer um deles como:
Isso imprimirá:
Para reverter a ordem (para alterá-la para a fila de prioridade máxima), basta alterar a ordem no comparador embutido ou usar
reversed
como:Também podemos usar
Collections.reverseOrder
:Portanto, podemos ver que
Collections.reverseOrder
está sobrecarregado para levar o comparador, que pode ser útil para objetos personalizados. Oreversed
realmente usaCollections.reverseOrder
:offer () vs add ()
De acordo com o documento
Ao usar uma fila com capacidade restrita, geralmente é preferível offer () adicionar (), que pode falhar ao inserir um elemento apenas lançando uma exceção. E PriorityQueue é uma fila de prioridade ilimitada com base em um heap de prioridade.
fonte
5
indica a capacidade inicial da fila?Apenas passe apropriado
Comparator
para o construtor :A única diferença entre
offer
eadd
é a interface à qual eles pertencem.offer
pertence aQueue<E>
, enquanto queadd
é originalmente visto naCollection<E>
interface. Além disso, os dois métodos fazem exatamente a mesma coisa - insira o elemento especificado na fila de prioridade.fonte
da API da fila :
fonte
não é diferente, como declara em javadoc:
fonte
Apenas para responder à pergunta
add()
vsoffer()
(já que a outra é perfeitamente respondida imo, e isso pode não ser):De acordo com JavaDoc na interface Queue , "O método offer insere um elemento, se possível, retornando false. Isso difere do método Collection.add, que pode falhar ao adicionar um elemento apenas lançando uma exceção não verificada. O método offer foi projetado para use quando a falha for uma ocorrência normal, e não excepcional, por exemplo, em filas de capacidade fixa (ou "limitada") ".
Isso significa que, se você pode adicionar o elemento (que sempre deve ser o caso em um PriorityQueue), eles funcionam exatamente da mesma maneira. Mas se você não pode adicionar o elemento,
offer()
ele fornecerá umfalse
retorno agradável e bonito , enquantoadd()
lança uma exceção desagradável e desmarcada, que você não deseja no seu código. Se a falha ao adicionar significa que o código está funcionando como pretendido e / ou é algo que você verificará normalmente, useoffer()
. Se a falha na adição significar que algo está quebrado, useadd()
e manipule a exceção resultante lançada de acordo com as especificações da interface Collection .Ambos são implementados dessa maneira para preencher o contrato na interface da Fila que especifica
offer()
falhas retornando umfalse
( método preferencial em filas com capacidade restrita ) e também mantêm o contrato na interface de Coleta que especificaadd()
sempre falhas ao lançar uma exceção .Enfim, espero que isso esclareça pelo menos essa parte da questão.
fonte
Aqui, podemos definir o comparador definido pelo usuário:
Diferença entre os métodos de oferta e adição: link
fonte
Passe um
Comparator
. Preencha o tipo desejado no lugar deT
Usando lambdas (Java 8+):
Maneira clássica, usando classe anônima:
Para ordenar na ordem inversa, basta trocar e1, e2.
fonte
Eu também estava pensando sobre a ordem de impressão. Considere este caso, por exemplo:
Para uma fila de prioridade:
Este código:
pode imprimir de maneira diferente de:
Encontrei a resposta de uma discussão em outro fórum , em que um usuário disse: "os métodos offer () / add () inserem apenas o elemento na fila. Se você deseja uma ordem previsível, deve usar o peek / poll que retorna a cabeça da fila ".
fonte
Como alternativa ao uso
Comparator
, você também pode ter a classe que está usando no seuPriorityQueue
implementoComparable
(e, sobrescrever, substituir ocompareTo
método).Observe que geralmente é melhor usar apenas em
Comparable
vez deComparator
se essa ordem for a ordem intuitiva do objeto - se, por exemplo, você tiver um caso de uso para classificarPerson
objetos por idade, provavelmente é melhor usar apenasComparator
.Resultado:
fonte
A fila de prioridade tem alguma prioridade atribuída a cada elemento. O elemento com maior prioridade aparece na parte superior da fila. Agora, depende de você como você deseja que a prioridade seja atribuída a cada um dos elementos. Caso contrário, o Java fará isso da maneira padrão. O elemento com o menor valor recebe a prioridade mais alta e, portanto, é removido da fila primeiro. Se houver vários elementos com a mesma prioridade mais alta, o empate será quebrado arbitrariamente. Você também pode especificar uma ordem usando o Comparator no construtor
PriorityQueue(initialCapacity, comparator)
Código de exemplo:
Resultado:
Senão, você também pode definir o Comparador Personalizado:
fonte
Aqui está o exemplo simples que você pode usar para o aprendizado inicial:
fonte