前言
栈和队列是两种特殊的线性表,是操作受限的线性表,称限定性DS通常称,栈和队列是限定插入和删除只能在表的“端点”进行的线性表
举例:
线性表 Insert(L,i, x) 1<=i<=n+1 Delete(L,i) 1<=i<=n //任意位置插入和删除
栈 Insert(S,n+1,x) Delete(S,n) //同一个口插入和删除
队列 Insert(Q, n+1,x) Delete(Q, 1) //一个口插入,另一个口删除
队列有单向队列(queue)和双向队列(deque)之分
一、Queue类的简介
Queue是Java中实现队列的接口,只有6个方法,一般只用其中3个就可以。Queue的实现类有LinkedList和PriorityQueue,最常用的实现类是LinkedList。
queue允许新增元素、移除元素、从最底端加人元素、从最顶端取出元素。!但除了最底端可以加入、最顶端可以取出外,没有任何其它方法可以存取queue的其它元素。换言之,queue不允许有遍历行为。
将元素推入queue的操作称为push,将元素推出queue的操作称为pop。
定义:队列是限定只能在表的一端进行插入,在表的另一端进行删除的线性表
队尾(rear)一-允许插入的一端
队头(front)--允许删除的一端
特点: 先进先出(FIFO)
1.Queue类方法的使用
1.1 add()与offer()添加元素方法
方法名称 | 功能描述 |
boolean add(E e) | 插入指定元素为该队列是否有可能立即这样做不违反容量限制 |
boolean offer(E e) | 在不违反容量限制的情况下,将指定的元素插入到队列中 |
同:未超出容量时,从队尾压入元素,函数返回压入的元素。
异:超出容量时,add(e)方法会抛出异常,offer(e)方法返回null。
//构建队列
Queue<String> queue = new LinkedList<>();
//添加元素:add(E e)将元素插入到当前队列中
queue.add("王大锤");
System.out.println("add以后结果:" + queue);
//添加元素:offer(E e)将元素插入到当前队列中
queue.offer("高圆圆");
queue.offer("佟丽娅");
queue.offer("马哥");
System.out.println("offer以后结果:" + queue);
注意:add(E e)与offer(E e)方法的区别:若操作的队列存在一个大小限制,即队列已经满队时,使用add方法将会抛出unchecked异常添加元素,此时add方法将不再适用,而采用offer方法将返回false,不对程序产生相关影响。
1.2 element()与peek()查看元素方法
方法名称 | 功能描述 |
E element() | 检索,但不删除此队列的头 |
E peek() | 检索,但不删除,这个队列头,或返回 null如果队列为空 |
同:容量大于0的时候,都返回队头元素,但是不删除元素。
异:容量为0的时候,element()方法会抛出异常,peek()方法返回null。
案例演示
Queue<String> queue = new LinkedList<>();
//添加元素:offer将元素插入到当前队列中
queue.offer("高圆圆");
queue.offer("佟丽娅");
queue.offer("马哥");
System.out.println("offer以后结果:" + queue);
//E peek()测试:检索但不删除队列的头部元素
System.out.println("peek头元素:" + queue.peek());
//E element()检索但不删除当前队列的头部元素。当头部元素为null,会报异常
System.out.println("element头元素:" + queue.element());
注意:peek()与element()方法区别:当队列为空的过程中,若使用element()方法查看头部元素时,程序将抛出 NoSuchElementException 异常,此时element方法不在适用,应该使用peek()方法查看头部元素,当队列为空时将会返回null,注意观察throws后的内容(if this queue is empty)
1.3 remove()与poll()删除元素方法
方法介绍
方法名称 | 功能描述 |
E remove( ) | 检索和删除此队列的头 |
E poll( ) | 检索并移除此队列的头,或返回 null如果队列为空 |
同:容量大于0的时候,删除并返回队头被删除的元素。
异:容量为0的时候,remove()方法会抛出异常,poll()方法返回null。
案例演示
Queue<String> queue = new LinkedList<>();
//添加元素:offer将元素插入到当前队列中
queue.offer("高圆圆");
queue.offer("佟丽娅");
queue.offer("马哥");
//获取头部元素并删除
System.out.println("poll头元素:" + queue.poll());
System.out.println("remove头元素:" + queue.remove());
注意:poll()与remove()方法区别:当队列为空的过程中,若使用remove()方法删除头部元素时,将抛出 NoSuchElementException 异常,此时remove( )方法不在适用,应该使用poll( )方法删除头部元素,当队列为空时将会返回null,注意观察throws后的内容(if this queue is empty)
二、Deque类的简介
Deque是一个双端队列接口,继承Queue接口,Deque的实现类是LinkedList、ArrayDeque和LinkedBlockingDeque,其中LinkedList是最常用的。其中LinkedBlockingDeque是一个基于链表实现的双向阻塞队列。
注意区分:LinkedBlockingQueue和LinkedBlockingDeque,两个都是队列,只不过前者只能一端出一端入,后者则可以两端同时出入,
Deque有三种用途:普通队列(一端进另一端出)、双端队列(两端都可进出)、堆栈。
普通队列
Queue queue = new LinkedList()或Deque deque = new LinkedList()
双端队列
Deque deque = new LinkedList()
Deque deque1 = new LinkedBlockingDeque();
LinkedBlockingDeque deque2 = new LinkedBlockingDeque();
堆栈
Deque deque = new LinkedList()
实际具体用法,我下面代码有展示
1、实体类
package cn.com.easyExcel.point;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* @author: ljyang
* @date: 2022/11/02
**/
@Data
@NoArgsConstructor
public class PointValue implements Serializable {
private static final long serialVersionUID = -3925356810846060856L;
// 值
public BigDecimal value;
// 某时刻
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
public LocalDateTime time;
public static PointValue of(BigDecimal value, LocalDateTime time) {
PointValue pointPower = new PointValue();
pointPower.setValue(value);
pointPower.setTime(time);
return pointPower;
}
}
2、赋值,执行方法
package cn.com.easyExcel.point;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Deque;
import java.util.LinkedList;
import java.util.concurrent.LinkedBlockingDeque;
/**
* 双向队列
*
* @author ljyang
* @date: 2022/11/02
**/
@Data
@NoArgsConstructor
public class PointValueQueue implements Serializable {
private static final long serialVersionUID = 5938295366928195243L;
private Long pointId;
private String pointName;
private LinkedBlockingDeque<PointValue> queue = new LinkedBlockingDeque<PointValue>();
public static PointValueQueue of(Long pointId, String pointName) {
PointValueQueue pointValueQueue = new PointValueQueue();
pointValueQueue.setPointId(pointId);
pointValueQueue.setPointName(pointName);
return pointValueQueue;
}
/**
* 新增元素, 队尾
*
* @param pointValue
*/
public void addLast(PointValue pointValue) {
this.queue.addLast(pointValue);
}
/**
* 获取队首元素值, 不移除, 队列为空时, 抛出异常
*
* @return
*/
@JsonIgnore
public PointValue getFirst() {
return this.queue.getFirst();
}
/**
* 获取队首元素值, 不移除, 队列为空时, 返回null
*
* @return
*/
@JsonIgnore
public PointValue peekFirst() {
return this.queue.peekFirst();
}
/**
* 获取队尾元素值, 不移除
*
* @return
*/
@JsonIgnore
public PointValue getLast() {
return this.queue.getLast();
}
/**
* 获取队首元素值, 移除
*
* @return
*/
public PointValue poll() {
return this.queue.poll();
}
/**
* 获取队列当前大小
*
* @return
*/
public int size() {
return this.queue.size();
}
/**
* 是否为空队列
*
* @return
*/
@JsonIgnore
public boolean isEmpty() {
return this.queue.isEmpty();
}
/**
* 清空
*/
public void clear() {
this.queue.clear();
}
}
3、调用方法,实现过程
package cn.com.easyExcel;
import cn.com.easyExcel.point.PointValue;
import cn.com.easyExcel.point.PointValueQueue;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* @author: ljyang
* @date: 2022/11/02
* @description:测试写队列
* LinkedBlockingQueue和LinkedBlockingDeque,两个都是队列,只不过前者只能一端出一端入,后者则可以两端同时出入,
* 并且都是结构改变线程安全的队列。其实两个队列从实现思想上比较容易理解,
* 有以下特点:
* 链表结构(动态数组)
* 通过ReentrantLock实现锁
* 利用Condition实现队列的阻塞等待,唤醒
*
*/
public class DequeDemoTest {
@Test
public void LinkedBlockingDeque() {
//字符串池
String key = StringPool.EMPTY;
Map<Long, PointValueQueue> queueMap = getSet();
for (int i = 0; i <20 ; i++) {
// 队列
PointValueQueue pointValueQueue = Optional.ofNullable(queueMap.get((long)i)).orElse(PointValueQueue.of((long)i, i+""));
System.out.println((i)+"之前::"+pointValueQueue);
// 队尾元素
PointValue tail = pointValueQueue.getLast();
// 队首元素
PointValue head = pointValueQueue.getFirst();
if(i%3==0){
//pointValueQueue.clear();
// 获取队首元素值, 移除
pointValueQueue.poll();
System.out.println((i)+"之后:::::"+pointValueQueue);
}
if(i==10){
pointValueQueue.clear();
System.out.println((i)+"最后:::::"+pointValueQueue);
}
}
}
//设置值
private Map<Long, PointValueQueue> getSet(){
Map<Long, PointValueQueue> roomSuspectedQueue=new HashMap<Long, PointValueQueue>();
for (int i = 0; i < 20; i++) {
PointValueQueue pointValueQueue = PointValueQueue.of((long)i, i + "");
for (int j = 0; j <10 ; j++) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime time = now.plusHours(j);
//功率
BigDecimal p = new BigDecimal(""+j);
// 队列新元素
PointValue pointValue = PointValue.of(p, time);
// 更新队列
pointValueQueue.addLast(pointValue);
}
roomSuspectedQueue.put((long)i,pointValueQueue);
}
return roomSuspectedQueue;
}
}