Java中PriorityQueue梳理和解析

1、概述

PriorityQueue 一个基于优先级的优先级队列。一定要与Collections中是sort区分开。此队列仅仅保证队首元素最小或者队首元素最大,可作为大根堆或者小根堆看待。队列中的元素按照其自然顺序(比如数值包装Integer、Long等类型,按照从小到大的顺序排序,注意,注意,注意,这个排序不是对全部元素进行排序,仅仅保证队首与剩余元素的关系。比如,如果按照自然顺序排序的话,假设有n个元素,排序后仅仅保证队首元素不大于剩下的n-1个元素,但是剩下的n-1个元素之间未必是非递减的。与Collections中的sort方法不同,sort是对所有元素进行排序,保证所有元素大小关系的一致性,左面都不大于右面或者左面都不小于后面。但是,PriorityQueue 中只保证队首与剩余元素的关系的一致性,队首不大于剩下的所有元素或者队首不小于剩下的所有元素)进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法。该队列不允许使用 null 元素也不允许插入不可比较的对象(没有实现Comparable接口的对象)。根据排序规则不同,PriorityQueue 队列的头指向排序规则中的最值元素。如果多个元素都是最值则随机选一个。PriorityQueue 是一个无界队列,但是初始的容量(实际是一个Object[]),随着不断向优先级队列添加元素,其容量会自动扩容,无需指定容量增加策略的细节。

2、常用方法

(1)构造方法:

       PriorityQueue()使用默认的初始容量(11)创建一个 PriorityQueue,并根据其自然顺序来排序其元素(使用 Comparable)。

       PriorityQueue(int initialCapacity)使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序来排序其元素(使用        Comparable)。

       PriorityQueue(int initialCapacity, Comparator comparator)使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器comparator来排序其元素。

(2)peek():返回队首元素

(3)poll():返回队首元素,队首元素出队列

(4)add():添加元素

(5)size():返回队列元素个数

(6)isEmpty():判断队列是否为空,为空返回true,不空返回false

3、关于排序规则

(1)普通类型:比如Integer,Long等类型,默认使用升序的排序方式,也即默认队首是最小的元素。如果想降序排列,则要自定义降序规则。

如下:k指定了初始容量,并通过new Comparator重写了compare方法,实现了降序规则

       PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
           @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1);
            }
        });

案例:

import java.util.PriorityQueue;
public class Main {
    public static void main(String[] args) {
       PriorityQueue<Integer> queue = new PriorityQueue<>();
       queue.add(0);
       queue.add(5);
       queue.add(1);
       queue.add(3);
       for(Integer fac : queue){
           System.out.println(fac);
       }
        System.out.println("------------");
        while(queue.size() != 0){
            System.out.println(queue.remove());
        }
    }
}

打印结果:

0
3
1
5
------------
0
1
3
5

分析:元素中加入0,5,1,3后打印的结果是0,3,1,5。可见队首0是最小的元素,队首不大于剩下的元素,而且剩下的元素未必是非递减的。while循环逐个删除打印队首并删除,结果是0,1,3,5,由此可知,每次删除元素后,队列都重新进行了排序,保证队首最小。

(2)自定义类型

两种定义排序规则的方式,如同Collections中的sort方法(可以参考Java中Collections.sort()案例讲解

(1)类实现接口

import java.util.PriorityQueue;
public class Main {
    public static void main(String[] args) {
       PriorityQueue<PriorityQueueTest> queue = new PriorityQueue<>();
       queue.add(new PriorityQueueTest(5,"world"));
       queue.add(new PriorityQueueTest(1,"bing"));
       queue.add(new PriorityQueueTest(3,"bao"));
       queue.add(new PriorityQueueTest(0,"hello"));
       for(PriorityQueueTest fac : queue){
           System.out.println(fac.num+" "+fac.name);
       }
        System.out.println("------------");
        while(queue.size() != 0){
            PriorityQueueTest removeFac = queue.remove();
            System.out.println(removeFac.getNum()+ " "+ removeFac.getName());
        }
    }
}
class PriorityQueueTest implements Comparable<PriorityQueueTest>{
    int num;
    String name;
    public PriorityQueueTest(int num, String name) {
        this.num = num;
        this.name = name;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    // 此类实现Comparable接口,重写了compareTo方法,自定义按照升序排列:按照num升序排序
    @Override
    public int compareTo(PriorityQueueTest o) {
        return this.num - o.num;
    }
}

打印结果:

0 hello
1 bing
3 bao
5 world
------------
0 hello
1 bing
3 bao
5 world

(2)在新建PriorityQueue实例时候,通过构造方法来的new Comparator参数来自定义排序规则

案例:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
public class Main {
    public static void main(String[] args) {
       PriorityQueue<PriorityQueueTest> queue = new PriorityQueue<PriorityQueueTest>(new Comparator<PriorityQueueTest>() {
           @Override
           public int compare(PriorityQueueTest o1, PriorityQueueTest o2) {
               return o2.getNum() - o1.getNum();
           }
       });
        queue.add(new PriorityQueueTest(5,"world"));
        queue.add(new PriorityQueueTest(1,"bing"));
        queue.add(new PriorityQueueTest(3,"bao"));
        queue.add(new PriorityQueueTest(0,"hello"));
       for(PriorityQueueTest fac : queue){
           System.out.println(fac.num+" "+fac.name);
       }
        System.out.println("------------");
        while(queue.size() != 0){
            PriorityQueueTest removeFac = queue.remove();
            System.out.println(removeFac.getNum()+ " "+ removeFac.getName());
        }
    }
}
class PriorityQueueTest{
    int num;
    String name;
    public PriorityQueueTest(int num, String name) {
        this.num = num;
        this.name = name;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

打印结果:

5 world
1 bing
3 bao
0 hello
------------
5 world
3 bao
1 bing
0 hello

可知,在PriorityQueue的构造方法中传入new Comparator,然后自定义compare方法来实现排序。

注意:PriorityQueue存储的元素要求必须是可比较的对象, 如果不是就必须明确指定比较器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值