当前位置:

首页 > 编程开发 > Java的栈和队列实例分析

Java的栈和队列实例分析

栈packagecom.yuzhenc.collection;importjava.util.Stack;/***@author:yuzhenc*@date:2022-03-2015:41:36*@desc:com.yuzhenc.collection*@version:1.0*/publicclassTest26{publicstaticvoidmain(String[]args){Stackstack=newStack();stack.add("A");stack.add("B");stack.add

本文目录

      栈

      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()));
          }
      }

      Java的栈和队列实例分析

      双端队列

      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]
          }
      }
      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发 Java
      相关文章 更多
      Java单元测试入门:使用JUnit 5编写第一个测试用例
      Java单元测试入门:使用JUnit 5编写第一个测试用例

      面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

      Java变量未初始化报错解析:局部变量与成员变量默认值差异
      Java变量未初始化报错解析:局部变量与成员变量默认值差异

      深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

      详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

      Java中final与static final常量的定义及初始化规则
      Java中final与static final常量的定义及初始化规则

      深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

      Java抽象方法与接口方法的区别及选型建议
      Java抽象方法与接口方法的区别及选型建议

      深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

      Java实现HTTP请求与JSON解析的完整代码示例
      Java实现HTTP请求与JSON解析的完整代码示例

      本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

      Java递归出现StackOverflowError的原因分析及栈空间优化方案
      Java递归出现StackOverflowError的原因分析及栈空间优化方案

      详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

      Java空指针异常(NPE)的代码排查与修复实例
      Java空指针异常(NPE)的代码排查与修复实例

      针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

      selenium上传文件教程本地文件路径设置方法
      selenium上传文件教程本地文件路径设置方法

      深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

      针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

      查看更多
      精品专题 更多
      装机必备
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows
      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程
      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      Mac软件 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      Aperty macOS版
      Aperty macOS版
      macOS

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      WINDOWS 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      PixTV 网页版
      PixTV 网页版
      Windows

      PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。