一起来学习Java的栈和队列

网友投稿 236 2022-08-18


一起来学习Java的栈和队列

目录栈队列阻塞队列双端队列总结

package com.yuzhenc.collection;

import java.util.Stack;

/**

* @author: yuzhenc

* @date: 2022-03-20 15:41:36

* @desc: com.yuzhenc.collection

* @version: 1.0

*/

public class Test26 {

public static void main(String[] args) {

Stack stack = new Stack<>();

stack.add("A");

stack.add("B");

stack.add("C");

stack.add("D");

System.out.println(stack);//[A, B, C, D]

//判断栈是否为空

System.out.println(stack.empty());//false

//查看栈顶元素,不会移除

System.out.println(stack.peek());//D

System.out.println(stack);//[A, B, C, D]

//查看栈顶元素,并且移除,即出栈(先进后出)

System.out.println(stack.pop());//D

System.out.println(stack);//[A, B, C]

//入栈,和add方法执行的功能一样,就是返回值不同

System.out.println(stack.push("E"));//返回入栈的元素 E

System.out.println(stack);//[A, B, C, E]

}

}

队列

阻塞队列

ArrayBlockingQueue : 不支持读写同时操作,底层基于数组的;LinkedBlockingQueue:支持读写同时操作,并发情况下,效率高,底层基于链表;

package com.yuzhenc.collection;

import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.TimeUnit;

/**

* @author: yuzhenc

* @date: 2022-03-20 16:00:22

* @desc: com.yuzhenc.collection

* @version: 1.0

*/

public class Test27 {

public static void main(String[] args) throws InterruptedException {

ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);

//添加元素

//不可以添加null,报空指针异常

//arrayBlockingQueue.add(null);

//arrayBlockingQueue.offer(null);

//arrayBlockingQueue.put(null);

//正常添加元素

System.out.println(arrayBlockingQueue.add("Lili"));//true

System.out.println(arrayBlockingQueue.offer("Amy"));//true

arrayBlockingQueue.put("Nana");//无返回值

//队列满的情况下添加元素

//arrayBlockingQueue.add("Sam");//报非法的状态异常

//设置最大注阻塞时间,如果时间到了队列还是满的,就不再阻塞了

arrayBlockingQueue.offer("Daming", 3,TimeUnit.SECONDS);

System.out.println(arrayBlockingQueue);//[Lili, Amy, Nana]

//真正阻塞的方法,如果队列一直是满的,就一直阻塞

//arrayBlockingQueue.put("Lingling");//运行到这永远走不下去了,阻塞了

//获取元素

//获取队首元素不移除

System.out.println(arrayBlockingQueue.peek());//Lili

//出队,获取队首元素并且移除

System.out.println(arrayBlockingQueue.poll());//Lili

System.out.println(arrayBlockingQueue);//[Amy, Nana]

//获取队首元素,并且移除

System.out.println(arrayBlockingQueue.take());//Amy

System.out.println(arrayBlockingQueue);//[Nana]

//清空元素

arrayBlockingQueue.clear();

System.out.println(arrayBlockingQueue);//[]

System.out.println(arrayBlockingQueue.peek());

System.out.println(arrayBlockingQueue.poll());

//设置阻塞事件,如果队列为空,返回null,时间到了以后就不阻塞了

System.out.println(arrayBlockingQueue.poll(2,TimeUnit.SECONDS));

//真正的阻塞,队列为空

//System.out.println(arrayBlockingQueue.take());//执行到这里走不下去了

}

}

SynchronousQueue:方便高效地进行线程间数据的传送,不会产生队列中数据争抢问题;

package com.yuzhenc.collection;

import java.util.concurrent.SynchronousQueue;

/**

* @author: yuzhenc

* @date: 2022-03-20 21:06:47

* @desc: com.yuzhenc.collection

* @version: 1.0

*/

public class Test28 {

public static void main(String[] args) {

SynchronousQueue sq = new SynchronousQueue();

//创建一个线程,取数据:

new Thread(new Runnable() {

@Override

public void run() {

while(true){

try {

System.out.println(sq.take());

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

//搞一个线程,往里面放数据:

new Thread(new Runnable() {

@Override

public void run() {

try {

sq.put("aaa");

sq.put("bbb");

sq.put("ccc");

sq.put("ddd");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}).start();

}

}

PriorityBlockingQueue:带优先级的阻塞队列;无界的队列,没有长度限制,但是在你不指定长度的时候,默认初始长度为11,也可以手动指定,当然随着数据不断的加入,底层(底层是数组Object[])会自动扩容,直到内存全部消耗殆尽了,导致 OutOfMemoryError内存溢出 程序才会结束;不可以放入null元素的,不允许放入不可比较的对象(导致抛ClassCastException),对象必须实现内部比较器或者外部比较器;

package com.yuzhenc.collection;

import java.util.concurrent.PriorityBlockingQueue;

/**

* @author: yuzhenc

* @date: 2022-03-20 21:16:56

* @desc: com.yuzhenc.collection

* @version: 1.0

*/

public class Test29 {

public static void main(String[] args) throws InterruptedException {

PriorityBlockingQueue priorityBlockingQueue = new PriorityBlockingQueue<>();

priorityBlockingQueue.put(new Human("Lili",25));

priorityBlockingQueue.put(new Human("Nana",18));

priorityBlockingQueue.put(new Human("Amy",38));

priorityBlockingQueue.put(new Human("Sum",9));

//没有按优先级排列

System.out.println(priorityBlockingQueue);//[Human{name='Sum', age=9}, Human{name='Nana', age=18}, Human{name='Amy', age=38}, Human{name='Lili', age=25}]

//出列的时候按优先级出列

System.out.println(priorityBlockingQueue.take());//Human{name='Sum', age=9}

System.out.println(priorityBlockingQueue.take());//Human{name='Nana', age=18}

System.out.println(priorityBlockingQueue.take());//Human{name='Lili', age=25}

System.out.println(priorityBlockingQueue.take());//Human{name='Amy', age=38}

}

}

class Human implements Comparable {

String name;

int age;

public Human() {}

public Human(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public String toString() {

return "Human{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

@Override

public int compareTo(Human o) {

return this.age-o.age;

}

DelayQueue:DelayQueue是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走;当生产者线程调用put之类的方法加入元素时,会触发Delayed接口中的compareTo方法进行排序,也就是说队列中元素的顺序是按到期时间排序的,而非它们进入队列的顺序。排在队列头部的元素是最早到期的,越往后到期时间越晚;消费者线程查看队列头部的元素,注意是查看不是取出。然后调用元素的getDelay方法,如果此方法返回的值小0或者等于0,则消费者线程会从队列中取出此元素,并进行处理。如果getDelay方法返回的值大于0,则消费者线程wait返回的时间值后,再从队列头部取出元素,此时元素应该已经到期;不能将null元素放置到这种队列中;DelayQueue能做什么淘宝订单业务:下单之后如果三十分钟之内没有付款就自动取消订单;饿了吗订餐通知:下单成功后60s之后给用户发送短信通知;关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之;缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出;任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求等;

package com.yuzhenc.collection;

import java.util.concurrent.DelayQueue;

import java.util.concurrent.Delayed;

import java.util.concurrent.TimeUnit;

/**

* @author: yuzhenc

* @date: 2022-03-20 21:43:32

* @desc: com.yuzhenc.collection

* @version: 1.0

*/

public class Test30 {

//创建一个队列:

DelayQueue dq = new DelayQueue<>();

//登录游戏:

public void login(User user){

dq.add(user);

System.out.println("用户:[" + user.getId() +"],[" + user.getName() + "]已经登录,预计下机时间为:" + user.getEndTime() );

}

//时间到,退出游戏,队列中移除:

public void logout(){

//打印队列中剩余的人:

System.out.println(dq);

try {

User user = dq.take();

System.out.println("用户:[" + user.getId() +"],[" + user.getName() + "]上机时间到,自动退出游戏");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

//获取在线人数:

public int onlineSize(){

return dq.size();

}

//这是main方法,程序的入口

public static void main(String[] args) {

//创建测试类对象:

Test30 test = new Test30();

//添加登录的用户:

test.login(new User(1,"张三",System.currentTimeMillis()+5000));

test.login(new User(2,"李四",System.currentTimeMillis()+2000));

test.login(new User(3,"王五",System.currentTimeMillis()+10000));

//一直监控

while(true){

//到期的话,就自动下线:

test.logout();

//队列中元素都被移除了的话,那么停止监控,停止程序即可

if(test.onlineSize() == 0){

break;

}

}

}

}

class User implements Delayed {

private int id;//用户id

private String name;//用户名字

private long endTime;//结束时间

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public long getEndTime() {

return endTime;

}

public void setEndTime(long endTime) {

this.endTime = endTime;

}

public User(int id, String name, long endTime) {

this.id = id;

this.name = name;

this.endTime = endTime;

}

//只包装用户名字就可以

@Override

public String toString() {

return "User{" +

"name='" + name + '\'' +

'}';

}

@Override

public long getDelay(TimeUnit unit) {

//计算剩余时间 剩余时间小于0 <=0 证明已经到期

return this.getEndTime() - System.currentTimeMillis();

}

@Override

public int compareTo(Delayed o) {

//队列中数据 到期时间的比较

User other = (User)o;

return ((Long)(this.getEndTime())).compareTo((Long)(other.getEndTime()));

}

}

双端队列

package com.yuzhenc.collection;

import java.util.Deque;

import java.util.LinkedList;

/**

* @author: yuzhenc

* @date: 2022-03-20 22:03:36

* @desc: com.yuzhenc.collection

* @version: 1.0

*/

public class Test31 {

public static void main(String[] args) {

/*

双端队列:

Deque extends Queue

Queue一端放 一端取的基本方法 Deque是具备的

在此基础上 又扩展了 一些 头尾操作(添加,删除,获取)的方法

*/

Deque d = new LinkedList<>() ;

d.offer("A");

d.offer("B");

d.offer("C");

System.out.println(d);//[A, B, C]

d.offerFirst("D");

d.offerLast("E");

System.out.println(d);//[D, A, B, C, E]

System.out.println(d.poll());//D

System.out.println(d);//[A, B, C, E]

System.out.println(d.pollFirst());//A

System.out.println(d.pollLast());//E

System.out.println(d);//[B, C]

}

}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:记一次springboot中用undertow的坑
下一篇:关于springboot
相关文章

 发表评论

暂时没有评论,来抢沙发吧~