Java优先队列PriorityQueue使用详解

目录

一、优先队列概述

  简介:

     API描述:

二、常用方法

     构造方法:

       方法摘要:

三、优先队列的使用

1.队列保存的是基本数据类型的包装类

2.队列保存的是自定义类

3.优先队列遍历

4.比较器生降序说明


 


 

一、优先队列概述

  简介:

          优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序,可以放基本数据类型的包装类(如:Integer,Long等)或自定义的类。对于基本数据类型的包装器类,优先队列中元素默认排列顺序是升序排列,对于自己定义的类来说,需要自己定义比较器

     API描述:

基于优先级堆的无限优先级queue 。 优先级队列的元素根据它们的有序natural ordering ,或由一个Comparator在队列构造的时候提供,这取决于所使用的构造方法。 优先队列不允许null元素。 依靠自然排序的优先级队列也不允许插入不可比较的对象(这样做可能导致ClassCastException )。

该队列的头部是相对于指定顺序的最小元素。 如果多个元素被绑定到最小值,那么头就是这些元素之一 - 关系被任意破坏。 队列检索操作pollremovepeekelement访问在队列的头部的元件。

类及其迭代器实现CollectionIterator接口的所有可选方法。 方法iterator()中提供的迭代器不能保证以任何特定顺序遍历优先级队列的元素。 如果需要有序遍历,请考虑使用Arrays.sort(pq.toArray())

请注意,此实现不同步。 如果任何线程修改队列,多线程不应同时访问PriorityQueue实例。 而是使用线程安全的PriorityBlockingQueue

实现注意事项:此实现提供了O(日志(n))的时间入队和出队方法( offerpollremove()add ); remove(Object)contains(Object)方法的线性时间; 和恒定时间检索方法( peekelementsize )。

二、常用方法

    以下基于JDK1.8版本,不同版本的JDK中方法略有不同,这个PriorityQueue自1.5开始,详情可自行查看官方API。

     构造方法:

PriorityQueue()                                                创建一个PriorityQueue ,具有默认的初始容量(11),根据它们的natural ordering对其元素进行排序

PriorityQueue(Collection<? extends E> c)                              创建一个 PriorityQueue集合中的元素的PriorityQueue。

PriorityQueue(Comparator<? super E> comparator)                         创建具有默认初始容量的 PriorityQueue ,并根据指定的比较器对其元素进行排序。

PriorityQueue(int initialCapacity)                                  创建PriorityQueue与根据它们的排序其元素指定的初始容量natural ordering

PriorityQueue(int initialCapacity, Comparator<? super E> comparator)          创建具有 PriorityQueue初始容量的PriorityQueue,根据指定的比较器对其元素进行排序。

PriorityQueue(PriorityQueue<? extends E> c)                            创建包含 PriorityQueue优先级队列中的元素的PriorityQueue。

PriorityQueue(SortedSet<? extends E> c)                               创建一个 PriorityQueue指定排序集中的元素的PriorityQueue。

  •  

       方法摘要:

Modifier and Type Method and Description
boolean add(E e)

将指定的元素插入到此优先级队列中。

void clear()

从此优先级队列中删除所有元素。

Comparator<? super E> comparator()

返回用于为了在这个队列中的元素,或比较null如果此队列根据所述排序natural ordering的元素。

boolean contains(Object o)

如果此队列包含指定的元素,则返回 true

Iterator<E> iterator()

返回此队列中的元素的迭代器。

boolean offer(E e)

将指定的元素插入到此优先级队列中。

E peek()

检索但不删除此队列的头,如果此队列为空,则返回 null

E poll()

检索并删除此队列的头,如果此队列为空,则返回 null

boolean remove(Object o)

从该队列中删除指定元素的单个实例(如果存在)。

int size()

返回此集合中的元素数。

Spliterator<E> spliterator()

在此队列中的元素上创建late-binding失败快速 Spliterator

Object[] toArray()

返回一个包含此队列中所有元素的数组。

元素没有特定的顺序。

返回的数组将是“安全的”,因为该队列不保留对它的引用。 (换句话说,这个方法必须分配一个新的数组)。 因此,调用者可以自由地修改返回的数组。

此方法充当基于阵列和基于集合的API之间的桥梁。

<T> T[] toArray(T[] a)

返回一个包含此队列中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。

三、优先队列的使用

1.队列保存的是基本数据类型的包装类

//自定义比较器,降序排列
	static Comparator<Integer> cmp = new Comparator<Integer>() {
	      public int compare(Integer e1, Integer e2) {
	        return e2 - e1;  //降序
	      }
	    };
	public static void main(String[] args) {
	        //不用比较器,默认升序排列
	        Queue<Integer> q = new PriorityQueue<>();
	        q.add(8);
	        q.add(5);
	        q.add(13);
	        q.add(2);
	        System.out.println("**********不使用比较器********************");
	        while(!q.isEmpty())
	        {
	            System.out.print(q.poll()+" ");
	        }
	        System.out.println();
	        System.out.println("**********使用比较器********************");
	        //使用自定义比较器,降序排列
	        Queue qq = new PriorityQueue(cmp);
	        qq.add(8);
	        qq.add(5);
	        qq.add(13);
	        qq.add(2);
	        while(!qq.isEmpty())
	        {
	            System.out.print(qq.poll()+" ");
	        }
	}

      结果:

**********不使用比较器********************
2 5 8 13 
**********使用比较器********************
13 8 5 2 

2.队列保存的是自定义类

	    //自定义比较类,先比较长,长升序排列,若长相等再比较宽,宽降序
	    static Comparator<Node> cNode=new Comparator<Node>() {
	        public int compare(Node o1, Node o2) {
	            if(o1.chang!=o2.chang)
	                return o1.chang-o2.chang;
	            else
	                return o2.kuan-o1.kuan;
	        }
	        
	    };
	    public static void main(String[] args) {
	    	Queue<Node> q=new PriorityQueue<>(cNode);
	        Node n1=new Node(1, 2);
	        Node n2=new Node(2, 5);
	        Node n3=new Node(2, 3);
	        Node n4=new Node(1, 2);
	        q.add(n1);
	        q.add(n2);
	        q.add(n3);
	        Node n;
	        while(!q.isEmpty())
	        {
	            n=q.poll();
	            System.out.println("长: "+n.chang+" 宽:" +n.kuan);
	        }
	    }
	

    结果:

长: 1 宽:2
长: 2 宽:5
长: 2 宽:3

3.优先队列遍历

  PriorityQueue的iterator()不保证以任何特定顺序遍历队列元素。

  若想按特定顺序遍历,先将队列转成数组,然后排序遍历

示例

Queue<Integer> q = new PriorityQueue<>(cmp);
        int[] nums= {2,5,3,4,1,6};
        for(int i:nums)
        {
            q.add(i);
        }
        Object[] nn=q.toArray();
        Arrays.sort(nn);
        for(int i=nn.length-1;i>=0;i--)
            System.out.print((int)nn[i]+" ");
        /**
         * 输出结果
         * 6 5 4 3 2 1 
         */

4.比较器生降序说明

Comparator<Object> cmp = new Comparator<Object>() {
        public int compare(Object o1, Object o2) {
            //升序
            return o1-o2;
            //降序
            return o2-o1;
        }
    };

猜你喜欢

转载自blog.csdn.net/qq_22596931/article/details/110421457