Cozile prioritare sunt utilizate foarte des în aplicațiile din viața reală. În acest articol vom afla ce cozi prioritare sunt și cum le putem folosi în Java.

Înainte de a discuta ce este o coadă prioritară, să vedem ce este o coadă obișnuită.

O coadă obișnuită urmează o structură first in first out (FIFO). Aceasta înseamnă că, dacă 3 mesaje – m1, m2 și m3 – intră în coadă în acea ordine, atunci acestea ies din coadă în exact aceeași ordine.

De ce avem nevoie de cozi?

Să spunem că avem producători de date (de exemplu, atunci când un utilizator face clic pe o pagină web) care sunt extrem de rapide. Dar apoi vrem să consumăm aceste date într-un ritm mai lent mai târziu.

În acest caz, producătorul ar împinge toate mesajele în coadă și un consumator ar consuma aceste mesaje ulterior din coadă într-un ritm mai lent.

Ce este o coadă prioritară?

După cum sa menționat mai devreme, o coadă obișnuită are o structură first in first out. Dar, în unele scenarii, vrem să procesăm mesajele într-o coadă pe baza priorității lor și nu pe baza momentului în care mesajul a intrat în coadă.

Cozile prioritare îi ajută pe consumatori să consume mai întâi mesajele cu prioritate mai mare, urmate de mesajele cu prioritate mai mică.

Cozi prioritare în Java

Acum să vedem câteva coduri Java reale care ne vor arăta cum să folosim cozile prioritare.

Cozi prioritare cu ordonare naturală

Iată câteva coduri care arată cum să creați o coadă de prioritate simplă pentru șiruri

private static void testStringsNaturalOrdering() {
        Queue<String> testStringsPQ = new PriorityQueue<>();
        testStringsPQ.add("abcd");
        testStringsPQ.add("1234");
        testStringsPQ.add("23bc");
        testStringsPQ.add("zzxx");
        testStringsPQ.add("abxy");

        System.out.println("Strings Stored in Natural Ordering in a Priority Queuen");
        while (!testStringsPQ.isEmpty()) {
            System.out.println(testStringsPQ.poll());
        }
    }

Prima linie ne spune că creăm o coadă prioritară:

Queue<String> testStringsPQ = new PriorityQueue<>();

PriorityQueue este disponibil în pachetul java.util.

În continuare adăugăm 5 șiruri în ordine aleatorie în coada de prioritate. Pentru aceasta folosim adăuga() funcționează așa cum se arată mai jos:

testStringsPQ.add("abcd");
testStringsPQ.add("1234");
testStringsPQ.add("23bc");
testStringsPQ.add("zzxx");
testStringsPQ.add("abxy");

Pentru a obține cel mai recent articol din coadă, folosim sondaj () funcționează așa cum se arată mai jos:

testStringsPQ.poll()

sondaj () ne va oferi cel mai recent element și, de asemenea, îl va elimina din coadă. Dacă dorim să obținem cel mai recent element din coadă fără a-l elimina, putem folosi arunca o privire() funcţie:

testStringsPQ.peek()

În cele din urmă, imprimăm toate elementele din coadă utilizând funcția poll () așa cum se arată mai jos:

while (!testStringsPQ.isEmpty()) {
   System.out.println(testStringsPQ.poll());
}

Iată rezultatul programului de mai sus:

1234
23bc
abcd
abxy
zzxx

Deoarece nu am spus cozii prioritare cum să-i prioritizăm conținutul, a folosit o comandă naturală implicită. În acest caz, ne-a redat datele în ordine crescătoare a șirurilor. Aceasta nu este aceeași ordine în care elementele au fost adăugate la coadă.

Ce zici de a avea o comandă personalizată?

Acest lucru este posibil, de asemenea, și o putem face cu ajutorul unui comparator.

Să creăm acum o coadă de priorități întregi. Dar de data aceasta să obținem rezultatul în ordinea descrescătoare a valorii.

Pentru a realiza acest lucru, mai întâi trebuie să creăm un comparator întreg:

 static class CustomIntegerComparator implements Comparator<Integer> {

        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 < o2 ? 1 : -1;
        }
    }

Pentru a crea un comparator, implementăm comparator interfață și suprascrieți fișierul comparaţie metodă.

Prin utilizarea o1 vom obține rezultatul în ordine descrescătoare. Dacă am fi folosit o1> o2? 1: -1, atunci am fi obținut rezultatul în ordine crescătoare

Acum că avem comparatorul, trebuie să adăugăm acest comparator la coada de prioritate. Putem face acest lucru astfel:

Queue<Integer> testIntegersPQ = new PriorityQueue<>(new CustomIntegerComparator());

Iată restul codului care adaugă elemente în coada de prioritate și le imprimă:

   testIntegersPQ.add(11);
        testIntegersPQ.add(5);
        testIntegersPQ.add(-1);
        testIntegersPQ.add(12);
        testIntegersPQ.add(6);

        System.out.println("Integers stored in reverse order of priority in a Priority Queuen");
        while (!testIntegersPQ.isEmpty()) {
            System.out.println(testIntegersPQ.poll());
        }

Ieșirea programului de mai sus este dată mai jos:

12
11
6
5
-1

Putem vedea că comparatorul și-a făcut treaba bine. Acum coada de prioritate ne oferă numerele întregi în ordine descrescătoare.

Coadă prioritară cu obiecte Java

Până în acest moment, am văzut cum putem folosi șiruri și numere întregi cu cozi prioritare.

În aplicațiile din viața reală, am folosi în general cozi prioritare cu obiecte Java personalizate.

Să creăm mai întâi o clasă numită CustomerOrder care este utilizată pentru a stoca detaliile comenzii clientului:

public class CustomerOrder implements Comparable<CustomerOrder> {
    private int orderId;
    private double orderAmount;
    private String customerName;

    public CustomerOrder(int orderId, double orderAmount, String customerName) {
        this.orderId = orderId;
        this.orderAmount = orderAmount;
        this.customerName = customerName;
    }

    @Override
    public int compareTo(CustomerOrder o) {
        return o.orderId > this.orderId ? 1 : -1;
    }

    @Override
    public String toString() {
        return "orderId:" + this.orderId + ", orderAmount:" + this.orderAmount + ", customerName:" + customerName;
    }

    public double getOrderAmount() {
        return orderAmount;
    }
}

Aceasta este o clasă Java simplă pentru a stoca comenzile clienților. Această clasă implementează interfață comparabilă, astfel încât să putem decide pe ce bază trebuie obiectat acest obiect în coada de prioritate.

Comanda este decisă de compara cu funcția în codul de mai sus. Linia o.orderId> this.orderId? 1: -1 instruiește ca ordinele să fie sortate în funcție de ordinea descrescătoare a Comanda ID camp

Mai jos este codul care creează o coadă de prioritate pentru obiectul CustomerOrder:

CustomerOrder c1 = new CustomerOrder(1, 100.0, "customer1");
CustomerOrder c2 = new CustomerOrder(3, 50.0, "customer3");
CustomerOrder c3 = new CustomerOrder(2, 300.0, "customer2");

Queue<CustomerOrder> customerOrders = new PriorityQueue<>();
customerOrders.add(c1);
customerOrders.add(c2);
customerOrders.add(c3);
while (!customerOrders.isEmpty()) {
	System.out.println(customerOrders.poll());
}

În codul de mai sus au fost create trei comenzi de clienți și adăugate la coada de prioritate.

Când rulăm acest cod, obținem următoarea ieșire:

orderId:3, orderAmount:50.0, customerName:customer3
orderId:2, orderAmount:300.0, customerName:customer2
orderId:1, orderAmount:100.0, customerName:customer1

După cum era de așteptat, rezultatul vine în ordinea descrescătoare a Comanda ID.

Ce se întâmplă dacă dorim să acordăm prioritate în funcție de orderAmount?

Acesta este din nou un scenariu real. Să presupunem că în mod implicit obiectul CustomerOrder este prioritizat de orderId. Dar atunci avem nevoie de un mod în care să putem acorda prioritate în funcție de orderAmount.

S-ar putea să credeți imediat că putem modifica fișierul compara cu funcție în CustomerOrder cLass la comandă în funcție de orderAmount.

Cu exceptia CustomerOrder cLass poate fi utilizat în mai multe locuri din aplicație și ar interfera cu restul aplicației dacă modificăm compara cu funcționează direct.

Soluția la aceasta este destul de simplă: putem crea un nou comparator personalizat pentru clasa CustomerOrder și să-l folosim împreună cu coada de prioritate

Mai jos este codul pentru comparatorul personalizat:

 static class CustomerOrderComparator implements Comparator<CustomerOrder> {

        @Override
        public int compare(CustomerOrder o1, CustomerOrder o2)
        {
            return o1.getOrderAmount() < o2.getOrderAmount() ? 1 : -1;
        }
    }

Acest lucru este foarte asemănător cu comparatorul întregului personalizat pe care l-am văzut mai devreme.

Linia o1.getOrderAmount() < o2.getOrderAmount() ? 1 : -1; indică faptul că trebuie să acordăm prioritate în funcție de ordinea descrescătoare a cantitatea comenzii.

Mai jos este codul care creează coada de prioritate:

  CustomerOrder c1 = new CustomerOrder(1, 100.0, "customer1");
        CustomerOrder c2 = new CustomerOrder(3, 50.0, "customer3");
        CustomerOrder c3 = new CustomerOrder(2, 300.0, "customer2");
        Queue<CustomerOrder> customerOrders = new PriorityQueue<>(new CustomerOrderComparator());
        customerOrders.add(c1);
        customerOrders.add(c2);
        customerOrders.add(c3);
        while (!customerOrders.isEmpty()) {
            System.out.println(customerOrders.poll());
        }

În codul de mai sus trecem comparatorul la coada de prioritate din următoarea linie de cod:

Queue<CustomerOrder> customerOrders = new PriorityQueue<>(new CustomerOrderComparator());

Mai jos este rezultatul când rulăm acest cod:

orderId:2, orderAmount:300.0, customerName:customer2
orderId:1, orderAmount:100.0, customerName:customer1
orderId:3, orderAmount:50.0, customerName:customer3

Putem vedea că datele apar în ordinea descrescătoare a ordinului Cantitate.

Cod

Toate codurile discutate în acest articol pot fi găsite în această repo GitHub.

felicitări ?

Acum știți cum să utilizați cozile prioritare în Java.

Despre autor

Îmi place tehnologia și urmăresc progresele în domeniu. De asemenea, îmi place să îi ajut pe ceilalți cu cunoștințele mele tehnologice.

Nu ezitați să vă conectați cu mine pe contul meu LinkedIn https://www.linkedin.com/in/aditya1811/

Poți să mă urmărești și pe twitter https://twitter.com/adityasridhar18

Simțiți-vă liber să citiți mai multe articole pe blogul meu la adityasridhar.com.