Filas
Java Collections - PriorityQueue
Como abordada inicialmente no tópico sobre listas, uma Queue
(fila) é designada para manter uma ordem de "coisas a fazer" ou a serem processadas de alguma forma.
Embora outras ordens sejam possíveis, filas geralmente são pensadas como FIFO (first in, first out). Filas suportam todos os métodos padrão de Collection
e também adicional métodos para adicionar, remover e revisar os elementos da fila.
PriorityQueue
PriorityQueue esta classe surgiu com o Java 5 com a proposta de proporcionar novos recursos considerando a já existente LinkeList
como o objetivo de criar filas consideradas prioritárias.
Vamos imaginar os seguintes cenários:
- Qual o critério de prioridade em uma fila de banco?
- Qual o critério de prioridade em um atendimento médico?
- Qual o critério de prioridade em um embarque de um avião?
Observe que nos cenários citados acima todos os objetos necessitarão eleger característica(s) de prioridade mediante um peso de comparação.
Como base no cenário 01, como identificar quais os clientes têm preferencia em serem atendidos? A partir de agora os objetos precisarão ser comparados entre si, e é ai que a entra em cena a interface java.lang.Comparable
.
import java.util.*;
public class FilasPrioridade {
public static void main(String[] args) {
PriorityQueue < Cliente > clientes = new PriorityQueue<>();
clientes.add(new Cliente("Jose", 1));
clientes.add(new Cliente("Marcos", 1));
clientes.add(new Cliente("Maria Lucia", 0));
clientes.add(new Cliente("Estefany", 1));
clientes.add(new Cliente("Joaquim da Silva", 0));
imprimirClientes(clientes);
}
// não se assuste com o nível de abstração, em breve você vai entender
static void imprimirClientes(Collection clientes){
System.out.println("***Listando os inscritos***");
for(Object cliente: clientes){
System.out.println(cliente);
}
}
}
class Cliente {
private String nome;
// 0 = preferencial / 1 = normal
private Integer prioridade;
public Cliente(String nome, Integer prioridade) {
this.nome = nome;
this.prioridade = prioridade;
}
public String getNome() {
return nome;
}
}
Acontecerá um erro de execução ao tentar executar o código acima.
Vamos aos esclarecimentos:
< Cliente >
- Não se assuste, iremos explicar mais detalhadamente no tópico Generics.- Na classe
Cliente
- Estamos utilizando um peso inteiro (0/1) para determinar 2 critérios de priorização. - Para um objeto ser comparado ele precisa ser comparável, é ai que se destaca o conceito de interfaces.
Vamos ajustar a classe cliente para ela poder ser comparável:
// Tornando a classe Cliente comparável
class Cliente implements Comparable<Cliente> {
private String nome;
// 0 = preferencial / 1 = normal
private Integer prioridade;
public Cliente(String nome, Integer prioridade) {
this.nome = nome;
this.prioridade = prioridade;
}
public String getNome() {
return nome;
}
@Override
public int compareTo(Cliente o) {
// valida se minha prioridade é superior ao outro elemento
// todas as classes Wrappers já comparáveis
return prioridade.compareTo(o.prioridade);
}
// Usamos o toString() para facilitar a impressão dos elementos que serão impressos
// Não use para finalidade da aplicação
@Override
public String toString() {
return "Cliente{" +
"nome='" + nome + '\'' +
", prioridade=" + prioridade +
'}';
}
}
Resultado da impressão dos clientes com base na prioridade de atendimento;
***Listando os clientes***
Cliente{nome='Maria Lucia', prioridade=0}
Cliente{nome='Joaquim da Silva', prioridade=0}
Cliente{nome='Jose', prioridade=1}
Cliente{nome='Estefany', prioridade=1}
Cliente{nome='Marcos', prioridade=1}
Vamos validar algumas operações básicas em nossa fila:
System.out.println("O próximo cliente da fila sera? " + clientes.peek());
System.out.println("Acabamos de atender o Senhor(a) " + clientes.poll());
System.out.println("Acabamos de atender o Senhor(a) " + clientes.poll());
clientes.add(new Cliente("Antonia Moreira", 0));
System.out.println("O próximo cliente da fila sera? " + clientes.peek());
O cenário 02 nos trás um pouco mais de organização quanto a priorização de nossos atendimentos destacando os níveis pré-estabelecidos conforme ilustração abaixo:
public enum NivelGravidade {
EMERGENCIA (0 ,0),
URGENCIA (1 ,60),
POUCO_URGENTE (2 ,120),
NAO_URGENTE (3 ,240);
private Integer prioridade;
private Integer minutosEspera;
private NivelGravidade (Integer prioridade,Integer minutosEspera){
this.prioridade = prioridade;
this.minutosEspera = minutosEspera;
}
public Integer getPrioridade() {
return prioridade;
}
public Integer getMinutosEspera() {
return minutosEspera;
}
}
PriorityQueue
herda seu toString() de java.util.AbstractCollection
, que não conhece ordens de classificação. (println usa toString() em todos os seus argumentos).
Se você pesquisar os elementos como pretendido, você os obterá na ordem correta.