欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java学习70:使用PriorityQueue

程序员文章站 2024-02-14 23:47:04
...

我们知道,Queue是一个先进先出的队列。

现在有一个这样的需求,我们知道在银行办理业务的时候需要排队拿号,这时候我们排队拿的号就是一个队列。但是这时候突然来了个VIP客户(没办法,人家有钱),拿到了号码是V1,于是柜台处理完上一个业务之后下一个本来轮到你的,但是还是叫的V1(很不爽,但是没办法)。现在我们需要实现的就是这样的一个插队的功能。

要实现这个功能,在队列这一知识点中,有一个队列叫优先队列PriorityQueue。

他和Queue的区别就是他的出队的顺序与元素的优先级有关,对PriorityQueue调用remove()或poll()方法,返回的总是优先级最高的元素。

我们还是上一串代码看看这个怎么实现的;
老规矩吧,创建包和文件,我丢一张图放着:
Java学习70:使用PriorityQueue

import java.util.PriorityQueue;
import java.util.Queue;

public class Demo10 {
    public static void main(String[] args) {
        Queue<String> q=new PriorityQueue<>();
        // 添加3个元素到队列:
        q.offer("apple");
        q.offer("pear");
        q.offer("banana");
        // 删除顶端元素
        System.out.println(q.poll()); // apple
        System.out.println(q.poll()); // banana
        System.out.println(q.poll()); // pear
        System.out.println(q.poll()); // null,因为队列为空
    }
}

Java学习70:使用PriorityQueue
我们看输出的结果,是不是很奇怪,输出的顺序和我们放进去的顺序不是一样的。有木有感觉似曾相识(疯狂暗示Map)。这是因为这个东西吧,内部也自带了一个Compareable接口。

如果我们要放入的元素并没有实现Compareable接口咋办?自己写撒,动手能力这么强,加油奥利给;
我们还是以银行排队的业务来为例子,实现一个PriorityQueue:

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

public class Demo10 {
    public static void main(String[] args) {
        Queue<User> q = new PriorityQueue<>(new UserComparator());
        // 添加3个元素到队列:
        q.offer(new User("Bob", "A1"));
        q.offer(new User("Alice", "A2"));
        q.offer(new User("Boss", "V1"));
        System.out.println(q.poll()); // Boss/V1
        System.out.println(q.poll()); // Bob/A1
        System.out.println(q.poll()); // Alice/A2
        System.out.println(q.poll()); // null,因为队列为空
    }
}

class UserComparator implements Comparator<User> {
    public int compare(User u1, User u2) {
        if (u1.number.charAt(0) == u2.number.charAt(0)) {
            // 如果两人的号都是A开头或者都是V开头,比较号的大小:
            return u1.number.compareTo(u2.number);
        }
        if (u1.number.charAt(0) == 'V') {
            // u1的号码是V开头,优先级高:
            return -1;
        } else {
            return 1;
        }
    }
}

class User {
    public final String name;
    public final String number;

    public User(String name, String number) {
        this.name = name;
        this.number = number;
    }

    public String toString() {
        return name + "/" + number;
    }
}

Java学习70:使用PriorityQueue
实现PriorityQueue的关键在于提供的UserComparator对象,它负责比较两个元素的大小(较小的在前)。UserComparator总是把V开头的号码优先返回,只有在开头相同的时候,才比较号码大小。

上面的UserComparator的比较逻辑其实还是有问题的,它会把A10排在A2的前面,请尝试修复该错误。

小结
PriorityQueue实现了一个优先队列:从队首获取元素时,总是获取优先级最高的元素。

PriorityQueue默认按元素比较的顺序排序(必须实现Comparable接口),也可以通过Comparator自定义排序算法(元素就不必实现Comparable接口)。

谢谢观看

上一篇: 关于favicon.ico的两三事

下一篇: