8 votes

Comparateur personnalisé Java PriorityQueueue

Dans ma PriorityQueue, j'ai deux types de clients, VIP et réguliers. Je veux d'abord servir les VIP, puis les clients réguliers.

Si CustomerID < 100, il est considéré comme VIP.

Si un client est VIP, il va à la fin de la partie VIP de la file d'attente.

Si un client est régulier, il va à la fin de toute la file d'attente.

En d'autres termes, je veux trier par valeur booléenne VIP, tout en conservant l'ordre d'arrivée des clients.

Voici ma classe d'ordre

public class Order implements Comparable<Order> {
    private final int customerID;
    private final int amount;
    private final boolean vip_status;

    public Order(int customerID, int amount) { 
        this.customerID = customerID;
        this.amount = amount;
        this.vip_status = customerID < 100 ? true : false;

    }

    @Override
    public int compareTo(Order o) {
        if (vip_status && !o.vip_status) {
            return -1;
        }
        if (!vip_status && o.vip_status)
            return 1;
        return 0;
    }

    public int getCustomerID() {
        return customerID;
    }

    public int getAmount() {
        return amount;
    }

    public boolean isVip_status() {
        return vip_status;
    }
}

Voici ma tentative pour remplir la file d'attente :

import java.util.PriorityQueue;

public class MyPriorityQueue {
    public static void main(String[] args) {
        PriorityQueue<Order> queue = new PriorityQueue<>();
        Order o1 = new Order(1, 50);
        Order o2 = new Order(5, 30);
        Order o3 = new Order(4, 10);
        Order o4 = new Order(150, 5);
        Order o5 = new Order(2, 5);
        Order o6 = new Order(200, 5);

        queue.add(o1);
        queue.add(o2);
        queue.add(o3);
        queue.add(o4);
        queue.add(o5);
        queue.add(o6);

        while(!queue.isEmpty()){
            Order s = queue.poll();
            System.out.printf("VIP Status: %s CustomerID: %s Amount: %s%n", 
                        s.isVip_status(), s.getCustomerID(), s.getAmount());
        }
    }
}

RÉSULTAT que j'obtiens (ce qui est faux) :

VIP Status: true CustomerID: 1 Amount: 50
VIP Status: true CustomerID: 5 Amount: 30
VIP Status: true CustomerID: 2 Amount: 5
VIP Status: true CustomerID: 4 Amount: 10
VIP Status: false CustomerID: 150 Amount: 5
VIP Status: false CustomerID: 200 Amount: 5

C'est ce que je m'attendais à voir (les CustomerID 2 et 4 devraient être dans le même ordre qu'ils sont arrivés) :

VIP Status: true CustomerID: 1 Amount: 50
VIP Status: true CustomerID: 5 Amount: 30
VIP Status: true CustomerID: 4 Amount: 10
VIP Status: true CustomerID: 2 Amount: 5
VIP Status: false CustomerID: 150 Amount: 5
VIP Status: false CustomerID: 200 Amount: 5

MISE À JOUR : Je ne veux pas trier par une autre colonne que VIP. Je ne veux pas ajouter "date" parce que cela ressemble à un hack, plutôt qu'à une compréhension du fonctionnement de Java.

4voto

Mike Nakis Points 7259

Il semble que le PriorityQueue La classe que Java fournit d'emblée. se sent libre de réorganiser les articles s'ils sont comparables les uns aux autres .

(Ce n'est pas "comment fonctionne Java", c'est juste une petite perversion au nom d'une certaine classe qui est fournie avec le Runtime Java).

Alors, voici quelque chose qui va probablement fonctionner :

  1. Introduire un nouveau OrderPlacement contenant a) un Order et b) un int priority .

  2. Dans votre PriorityQueue ajouter OrderPlacement au lieu de Order objets.

  3. Lorsque vous créez une nouvelle OrderPlacement émet un nouvel objet priority pour elle, en incrémentant un compteur.

Ensuite, votre OrderPlacement peut avoir un compareTo() qui ressemble à ceci :

@Override
public int compareTo( OrderPlacement o ) 
{
    int d = -Boolean.compare( order.vip_status, o.order.vip_status );
    if( d != 0 )
        return d;
    return Integer.compare( priority, o.priority );
}

2voto

Nilesh Rajani Points 483

Si vous doit faites-le en utilisant la file d'attente prioritaire, le code ci-dessous résoudra votre problème. Notez que j'utilise un compteur statique pour maintenir l'ordre correct des éléments avec le même statut VIP car les éléments égaux sont maintenus dans un ordre aléatoire dans la file d'attente prioritaire. Cela est dû au fait que la file d'attente prioritaire utilise une structure de données min/max du tas et qu'elle ne se soucie que de placer l'élément min/max au sommet du tas et ne se soucie pas de l'ordre des mêmes éléments.

import java.util.PriorityQueue;

public class Order implements Comparable<Order> {
  private final int customerID;
  private final int amount;
  private final int vip_status;
  private final int score;
  private static int counter = 0;

  public Order(int customerID, int amount) {
    this.customerID = customerID;
    this.amount = amount;
    this.vip_status = customerID < 100 ? 0 : 1;
    this.score = counter++;
  }

  @Override
  public String toString() {
    return customerID + " : " + amount + " : " + vip_status;
  }

  @Override
  public int compareTo(Order o) {
    int status = ((Integer) this.vip_status).compareTo(o.vip_status);
    status = status == 0 ? ((Integer) this.score).compareTo(o.score) : status;
    return status;
  }

  public static void main(String[] args) {
    Order o1 = new Order(1000, 100);
    Order o2 = new Order(500, 100);
    Order o3 = new Order(99, 100);
    Order o4 = new Order(10, 100);
    Order o5 = new Order(200, 100);
    Order o6 = new Order(1, 100);

    PriorityQueue<Order> orderQueue = new PriorityQueue<>();
    orderQueue.offer(o1);
    orderQueue.offer(o2);
    orderQueue.offer(o3);
    orderQueue.offer(o4);
    orderQueue.offer(o5);
    orderQueue.offer(o6);

    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
  }
}

`

Exemple de sortie :

99 : 100 : 0
10 : 100 : 0
1 : 100 : 0
1000 : 100 : 1
500 : 100 : 1
200 : 100 : 1

Note : vous devez être conscient que le score peut éventuellement atteindre Integer.MAX_VALUE

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X