队列的使用:一般情况下,如果是对一些及时消息的处理,并且处理时间很短的情况下是不需要队列的,直接阻塞式的方法调用就可以了。但是如果在消息处理的时候特别费时间,这个时候如果有新消息来了,就只能处于阻塞状态,造成用户等待。这个时候便需要引入队列了。当接收到消息后,先把消息房贷队列中,然后再用行的线程进行处理,这个时候就不会有消息阻塞了。
个人认为消息队列的主要特点是异步处理,主要目的是减少请求响应时间和解耦。所以主要的使用场景就是将比较耗时而且不需要即时(同步)返回结果的操作作为消息放入消息队列。同时由于使用了消息队列,只要保证消息格式不变,消息的发送方和接收方并不需要彼此联系,也不需要受对方的影响,即解耦和。
Queue的实现
1、没有实现的阻塞接口的LinkedList: 实现了java.util.Queue接口和java.util.AbstractQueue接口
内置的不阻塞队列: PriorityQueue 和 ConcurrentLinkedQueue
PriorityQueue 和 ConcurrentLinkedQueue 类在 Collection Framework 中加入两个具体集合实现。
PriorityQueue 类实质上维护了一个有序列表。加入到 Queue 中的元素根据它们的天然排序(通过其 java.util.Comparable 实现)或者根据传递给构造函数的 java.util.Comparator 实现来定位。
ConcurrentLinkedQueue 是基于链接节点的、线程安全的队列。并发访问不需要同步。因为它在队列的尾部添加元素并从头部删除它们,所以只要不需要知道队列的大 小, ConcurrentLinkedQueue 对公共集合的共享访问就可以工作得很好。收集关于队列大小的信息会很慢,需要遍历队列。
2)实现阻塞接口的:
java.util.concurrent 中加入了 BlockingQueue 接口和五个阻塞队列类。它实质上就是一种带有一点扭曲的 FIFO 数据结构。不是立即从队列中添加或者删除元素,线程执行操作阻塞,直到有空间或者元素可用。
五个队列所提供的各有不同:
* ArrayBlockingQueue :一个由数组支持的有界队列。
* LinkedBlockingQueue :一个由链接节点支持的可选有界队列。
* PriorityBlockingQueue :一个由优先级堆支持的无界优先级队列。
* DelayQueue :一个由优先级堆支持的、基于时间的调度队列。
* SynchronousQueue :一个利用 BlockingQueue 接口的简单聚集(rendezvous)机制。
例题:给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
窗口大于数组长度的时候,返回空。
package Linkedlist;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
String[] nums = str.split(",");
int[] num = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
num[i] = Integer.parseInt(nums[i]);
}
int windowSize = sc.nextInt();
System.out.println(maxInWindows(num, windowSize));
}
public static ArrayList<Integer> maxInWindows(int[] num, int size) {
ArrayList<Integer> arrayList = new ArrayList<>();
if(size>num.length){
return arrayList;
}
//Queue<Integer> queue = new LinkedList<>();//LinkedList实现了queue
//Queue<Integer> queue = new PriorityQueue<>();//插入的数据会被排序,从小到大排列
PriorityQueue<Integer> queue = new PriorityQueue<>((o1, o2) -> o2 - o1); //大顶堆
int max = 0;
for (int i = 0; i < num.length - size+1; i++) {
for (int j = i; j < i + size; j++) {
queue.offer(num[j]);
}
// while(queue!=null && queue.size()!= 0) {
// int temp;
// temp = queue.poll();
// max = Math.max(max, temp);
// // queue.poll();
// }
// if(max != 0&& max != num.length){
// arrayList.add(max);
arrayList.add(queue.peek());
// }
// max = 0;
queue.clear();
}
return arrayList;
}
}
数据结构拓展:
一、队列
Queue<Integer> queue = new LinkedList<>();//声明队列
queue.add(1);//添加数据
queue.offer(1);//添加数据
//add() offer()都是想队尾插入数据 区别是add()方法插入数据超出队列界限时候会抛出异常,而offer()方法是返回false
queue.poll();//输出队列
queue.peek();//输出队列但不删除
queue.remove();//输出队列
//在队列元素为空的情况下,remove() 方法会抛出NoSuchElementException异常,poll() 方法只会返回 null
Queue<Integer> queString = new PriorityQueue<>();//插入的数据会被排序,小顶堆
PriorityQueue<Integer> queue = new PriorityQueue<>((o1, o2) -> o2 - o1); //大顶堆
二、栈
Stack stack1 = new Stack();
Stack<String> stackString = new Stack<>();
stackString.pop();//输出元素,栈为空的时候会抛出异常
stackString.add();//添加元素
stackString.push();//添加元素
//add是继承自Vector的方法,且返回值类型是boolean。
//push是Stack自身的方法,返回值类型是参数类类型
三、Hashmap
Map<String,String> map = new HashMap();//创建map
for(Map.Entry<String,String> entry : map.entrySet()){
System.out.println(entry.getValue());
System.out.println(entry.getKey());
}
//Map.Entry 是Map中的一个接口,他的用途是表示一个映射项(里面有Key和Value)
//Map.entrySet() 这个方法返回的是一个Set<Map.Entry<K,V>>表示一个映射项的Set。
//Map.Entry里有相应的getKey和getValue方法,即JavaBean,让我们能够从一个项中取出Key和Value。