队列和栈的学习

           java队列和栈的学习

本章学习了Queue和Deque的主要方法,很多东西都是可以从源码中直接查到的,可以进行基础学习。

  首先看一下Queue集合的主要的一个子接口Deque:双端队列

几个重要的实现类:

ArrayDeque,PriorityQueue,LinkedList,还有几个基于多线程的队列,栈的实现:

ArrayBlokingQueue

,concurrentLinkedListQueue,

LinkedBlockingQueue,

PriorityBlockingQueue,等主要的几个。

首先看一下Queue的几个方法的使用:

实例代码一:

/**
 * Queue接口方法的使用介绍
 * Queue有一个PriorityQueue的实现类,还有一个Deque的接口,代表一个双端队列。
 * 双端队列可以同时从两端添加和删除数据,因此可以当成队列和栈来使用,其有两个实现类,。
 * ArrayDeque和LinkedList
 * @author fcs
 *
 */
public class QueueDemo {
    public static void main(String[] args) {
		Queue queue = new ArrayDeque();
		queue.add("string");  //将指定的元素加入队列的尾部
		queue.add("double");
		queue.offer("int");   //将指定的元素加入队列的尾部,,当使用有限容量的队列时,该方法比add性能好。
		System.out.println(queue);
		Object obj = queue.element();   //获取队头元元素但是不删除。
		System.out.println("obj = "+obj);
		obj = queue.peek();         //获取队头元素,如果此队列为空则返回null
		System.out.println("obj = "+obj);
		obj = queue.poll();         //获取队头元素,如果此队列为空则返回null
    }
}

在JDK中Queue有两种形式的方法:一种是抛出异常(操作失败时),另一种是返回特殊值(根据具体情况)

 

抛出异常

返回特殊值

插入

add(e)

offer(e)

移除

remove()

poll()

检查

element()

peek()

在添加元素的offer方法中,用于专门为有容量限制的Queue设计的,在大多数实现中通常不会产生异常。

注意Queue的两点:

1.    Queue的实现通常不允许元素为null,LinkedList除外,当然null可以作为poll方法的返回值,并不会在没有元素的情况下抛出异常。

2.    Queue的实现通常没有定义equals方法和hashcode方法的基于元素比较的方式,而是从Object中继承了基于身份的版本,这是由于具有相同元素但是有不同排序属性的队列而言,基于元素的相等性和比较性并不能满足排序的需求。

第二:ArrayDeque实现作为“栈“的使用方式

实例代码二:

/**
 * ArrayDeque的作为栈的使用方式
 * 两种:
 * 1.直接使用
 * 2.进行封装使用
 * @author fcs
 *
 */
public class ArrayDequeDemo {
  public static void main(String[] args) {
	  //第一种方式: 使用自己的对象创建
	  ArrayDeque<String>  arrdeque = new ArrayDeque<String>();
	  arrdeque.push("Java");                 //内部调用的是addFirst();方法
	  arrdeque.push("c++");
	  arrdeque.push("andriod");
	  System.out.println(arrdeque);
	  System.out.println(arrdeque.peek());   //访问第一个元素,内部调用的是peekFirst方法
	  System.out.println(arrdeque.pop());    //访问第一个元素,并弹出栈顶元素,内部调用的是peekFirst()方法,
	                                         //然后peekFirst方法再次调用pollFirst()方法
	  System.out.println(arrdeque); 
	  
	  //第二种方式:直接使用内部实现的方法进行封装
	  StackInt   stack = new StackInt();
	  for(int i = 0;i < 6;i++){
		  stack.push(i+1);
	  }
	  System.out.println(stack);
	  System.out.println("访问第一个元素: "+stack.peek());
	  System.out.println("删除第一个元素: "+stack.pop());
	  System.out.println(stack);
  }
}

class StackInt{
	private Deque<Integer>  deque = new ArrayDeque<Integer>();
	public void push(Integer ele){
		deque.addFirst(ele);
	}
	public Integer pop(){
		return deque.removeFirst();
	}
	public Integer peek(){
		return deque.peekFirst();
	}
	public String toString(){
		return deque.toString();
	}
}

第三:PriorityQueue优先队列的练习和注意要点:

1.PriorityQueue是一个基于堆的无界优先级队列,默认使用按照自然排序的方式,当然可以通过提供的Comparator接口进行定制排序。

2.在自然排序中,如果插入的对象不同会引发ClassCastException.

3.默认队列的头是按指定排序的最小值,访问处于队列头部元素的方法有:

Poll(访问,并弹出元素)remove(访问并弹出元素)peek(只访问元素)element(只访问元素)

4.该优先级队列的数据结构是采用数组的方式,数组大小会动态增加,容量无限,不过建议如果数据量比较大的时候先初始化一个比较大的容量,以免扩容多次影响性能。

5.此实现方式不是同步的,也就是说不是线程安全的,如果多个线程中的任意线程从结构上修改了列表元素,则这些线程不应该同时访问PriorityQueue的实例,可以使用基于线程安全的PriorityBlockingQueue类。

6.此实现的插入方法(offer,poll,remove,add)的时间复杂度为O(log(n)),removeObject obj)和containsObject obj)方法提供线性的时间复杂度。

为检索方法(peek,elementsize)方法提供固定时间的复杂度。

7.可以在构造函数中指定如何排序,

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

PriorityQueueintinitialCapacity,Comparator comparator:使用指定的初始容量创建一个PriorityQueue,并根据其自然顺序排序元素,使用指定的比较器comparator接口。

8.此类及其迭代器实现了CollectionIterator接口的所有可选方法 

PriorityQueue的内部实现:

PriorityQueue对元素采用的是堆排序,头是按指定排序方式的最小元素,堆排序只能保证根是最大(最小),整个堆并不是有序的,

方法Iteatro()中提供的迭代器可以能呢过只是对整个数组的依次遍历,也就是只能保证数组的第一个元素是最小的。

实例代码三:
/**
 * Queue的实现类PriorityQueue的实现练习
 * @author fcs
 * PriorityQueue是一个比较标准的队列实现,因为该实现类保存队列元素的顺序并不是按照加入队列的顺序,而是按照
 * 队列元素的大小进行重新排列,在进行peek,或者poll操作时,并不是取出的是  
 */
public class PriorityQueueDemo {
   public static void main(String[] args) {
	  PriorityQueue   pqueue = new PriorityQueue();
	  pqueue.offer(6);
	  pqueue.offer(-2);
	  pqueue.offer(5);
	  pqueue.offer(1232);
	  System.out.println(pqueue);    //注意输出的顺序并不是绝对按照大小进行输出的,原因是默认使用了tostring方法进行的转换。
	  System.out.println("size = "+pqueue.size());
	  //不过每次从队列中取出数据的poll方法可以看到元素从小到大的顺序“移出队列”
	  
	  //使用for循环不能全部遍历,不知道为什么?????
	 for(int i =0 ; i < pqueue.size();i++){
		 System.out.println(pqueue.poll());
	 }
	  
	 //而下面这种方式就可以
	 while(!pqueue.isEmpty()){
		 System.out.println(pqueue.poll());
	 }
   }
}

这里有个问题:不过不是经常遇到,就是说使用基本的for循环对某些特殊的数据结构中的元素进行遍历的时候,不会遍历到最后,而只是遍历一部分就停止了,现在这个问题又出现了。有点不知为何。

对于该优先级队列的两种排序方式下面给出代码:

 实例代码四:

/**
 * 对PriorityQueue实现自然排序,和定制排序测试
 * @author fcs
 *
 */
@SuppressWarnings("rawtypes")
class  Goods implements Comparable{
	private int id;
	private double price;
	private String name;
	private String type;
	public Goods(){
		
	}
	public Goods(int id, double price, String name, String type) {
		this.id = id;
		this.price = price;
		this.name = name;
		this.type = type;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}

	//重写compareTo方法,按照id进行自然排序
	@Override
	public int compareTo(Object o) {
		Goods goods = (Goods)o;
		return this.id < goods.id ? 1:
			  this.id > goods.id ? -1:0;
	}
}

public class SortPriorityQueue {
   public static void main(String[] args) {
	   //自然排序实例测试
	   PriorityQueue<Goods> pqueue = new PriorityQueue<Goods>();
	   pqueue.offer(new Goods(2,234.1,"苹果","水果"));
	   pqueue.offer(new Goods(1,24.234,"橡胶","木材"));
	   pqueue.offer(new Goods(1,24.234,"橡胶","木材"));
	   pqueue.offer(new Goods(5,2.00,"雪糕","零食"));
	   pqueue.offer(new Goods(5,2.00,"雪糕","零食"));
	//第一种遍历方式
	   while(!pqueue.isEmpty()){
		   System.out.println(pqueue.poll().getId());
	   }
	   System.out.println();
	   //第二种遍历方式:使用Iterator接口
	   Iterator<Goods> itGoods =  pqueue.iterator();
	   while(itGoods.hasNext()){
		   System.out.print(itGoods.next().getId()+"--");
	   }	   
	   //定制排序实例,创建的PriorityQueue需要一个初始化队列的容量值和一个Comparator对象,进行定制排序
	   Comparator<Goods1>  comparator = new Comparator<Goods1>(){
		@Override
		public int compare(Goods1 o1, Goods1 o2) {
			return  o2.getPrice() - o1.getPrice() ;
		}
	   };
	   PriorityQueue<Goods1> pqueue1 = new PriorityQueue<Goods1>(5,comparator);
	   pqueue1.offer(new Goods1(2,20,"键盘"));
	   pqueue1.offer(new Goods1(1,40,"鼠标"));
	   pqueue1.offer(new Goods1(3,5004,"电脑"));
	   while(!pqueue1.isEmpty()){
		   Goods1 goods = pqueue1.poll();
		   System.out.print(goods.getId()+"--"+goods.getPrice()+" , ");
	   }
   }
}

/**
 * 采用定制排序的第一种方式:
 * 类实现comparator接口,并实现compare方法作为排序标准
 * @author fcs
 *
 */
class  Goods1{
	private int id;
	private int price;
	private String name;
	public Goods1(){}
	
	public Goods1(int id, int price, String name) {
		this.id = id;
		this.price = price;
		this.name = name;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值