【问题标题】:Sorting PriorityQueue排序优先队列
【发布时间】:2012-11-01 01:03:38
【问题描述】:

我在使用 PriorityQueues 时遇到问题,因为我相信它按优先级排序,但是我不确定优先级是什么(我的意思是值是什么以及它来自哪里)。可以在构造函数中使用比较器来创建 priorityQueue,我已经尝试过了,但它不起作用。

队列类:

public JavaPriorityFlightQueue() {
    super();
    flights = new PriorityQueue(5, new SortQueueViaPriority());
}

比较器:

import java.util.Comparator;

public class SortQueueViaPriority implements Comparator {

    public int compare(Object o1, Object o2){
        Flight f1 = (Flight) o1; 
        Flight f2 = (Flight) o2;

        if( f1 == null || f2 == null ){
            if( f1 == f2 ) return 0;
            else if( f2 == null) return +1;
                else return -1;
        }

    Integer i1 = (Integer) f1.getPriority();
    Integer i2 = (Integer) f2.getPriority();
    return i2.compareTo(i1);
    }
}

Priority 是一个 int 值,它是航班类别的一部分。我测试一下。

JavaPriorityFlightQueue flightQueue = new JavaPriorityFlightQueue();

Flight flight1 = new Flight("0001",9);
Flight flight2 = new Flight("0002",7);
Flight flight3 = new Flight("0003",1);
Flight flight4 = new Flight("0004",2);
Flight flight5 = new Flight("0005",1);

但是 PriorityQueue 没有排序,当我检查它时,值 9 从未与任何内容进行比较,结果是没有任何内容被排序。比较类 SortQueueViaPriority 是从该类完美排序的另一个类复制和粘贴的。

【问题讨论】:

标签: java sorting priority-queue


【解决方案1】:

我建议你试试下面的例子。如果将 PriorityQueue 用作队列,则条目将按顺序删除。

import java.util.Comparator;
import java.util.PriorityQueue;

public class Main {
    public static void main(String... args) {
        PriorityQueue<Flight> flights = new PriorityQueue<Flight>(5, new SortQueueViaPriority());
        flights.add(new Flight("0001", 9));
        flights.add(new Flight("0002", 7));
        flights.add(new Flight("0003", 1));
        flights.add(new Flight("0004", 2));
        flights.add(new Flight("0005", 1));

        while (!flights.isEmpty())
            System.out.println(flights.remove());
    }
}

class SortQueueViaPriority implements Comparator<Flight> {
    @Override
    public int compare(Flight f1, Flight f2) {
        return Integer.compare(f2.getPriority(), f1.getPriority());
    }
}

class Flight {
    private final String name;
    private final int priority;

    Flight(String name, int priority) {
        this.name = name;
        this.priority = priority;
    }

    public int getPriority() {
        return priority;
    }

    @Override
    public String toString() {
        return "Flight{" +
                "name='" + name + '\'' +
                ", priority=" + priority +
                '}';
    }
}

打印

Flight{name='0001', priority=9}
Flight{name='0002', priority=7}
Flight{name='0004', priority=2}
Flight{name='0003', priority=1}
Flight{name='0005', priority=1}

注意:PriorityQueue 对条目进行排序,使得只有第一个元素是最小的。如果您遍历队列,您将看到所有元素,但它们可能按顺序排列,也可能不按顺序排列。

【讨论】:

  • @dacwe 正确,这就是 OP 在任何情况下实现它的方式。
  • 航班 [flightID=0003, priority=1] 航班 [flightID=0005, priority=1] 航班 [flightID=0002, priority=7] 航班 [flightID=0001, priority=9] 航班 [航班ID=0004,优先级=2]
  • 正如我最后指出的,这是意料之中的。
【解决方案2】:

问题是Iterator。如Java doc of PriorityQueue#iterator 中所述

返回此队列中元素的迭代器。迭代器不会以任何特定顺序返回元素。

由于toString 使用迭代器,它不会按顺序打印。或者如果你使用基于迭代器的循环,那么它也将是有序的。

而在Java doc of PriorityQueue

队列检索操作 poll、remove、peek 和 element 访问队列头部的元素。

要按顺序获得结果,您必须使用其中一种方法。

【讨论】:

    【解决方案3】:

    使用Comparable 接口代替Comparator

    您的 Flight 类应该实现 Comparable 接口。然后你需要重写compareTo() 方法。在该方法中,您可以根据需要添加自己的排序逻辑。

    就像这样:

    @Override
    public int compareTo(Object obj) {
        // TODO Auto-generated method stub
        Flight f = (Flight)obj;
        if(this.a <f.a){
        return 1;
        }else{
            return -1;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多