服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 一起来学习Java的栈和队列

一起来学习Java的栈和队列

2022-10-12 13:07sqlboy-yuzhenc Java教程

这篇文章主要为大家详细介绍了Java的栈和队列,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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<String> 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:支持读写同时操作,并发情况下,效率高,底层基于链表;
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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<String> 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:方便高效地进行线程间数据的传送,不会产生队列中数据争抢问题;

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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),对象必须实现内部比较器或者外部比较器;
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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<Human> 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 <Human> {
    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之后给用户发送短信通知;
    • 关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之;
    • 缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出;
    • 任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求等;
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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<User> 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的栈和队列

双端队列

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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<E> extends Queue
        Queue一端放 一端取的基本方法  Deque是具备的
        在此基础上 又扩展了 一些 头尾操作(添加,删除,获取)的方法
         */
        Deque<String> 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]
    }
}

总结

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

原文链接:https://blog.csdn.net/qq_33445829/article/details/123614633

延伸 · 阅读

精彩推荐
  • Java教程超实用的Java快捷键(总结)

    超实用的Java快捷键(总结)

    下面小编就为大家带来一篇超实用的Java快捷键(总结)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Java之家2992020-10-05
  • Java教程Java面试题冲刺第十三天--数据库(3)

    Java面试题冲刺第十三天--数据库(3)

    这篇文章主要为大家分享了最有价值的三道数据库面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,感兴趣的小伙伴们可以参...

    _陈哈哈9542021-10-09
  • Java教程Java循环对bean的属性进行赋值的实现

    Java循环对bean的属性进行赋值的实现

    本文主要介绍了Java循环对bean的属性进行赋值,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    BHBshy6532021-11-26
  • Java教程Java修改图片大小尺寸的简单实现

    Java修改图片大小尺寸的简单实现

    这篇文章主要介绍了Java修改图片大小尺寸的简单实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...

    西凉的悲伤10372022-01-07
  • Java教程Spring Boot FeignClient 如何捕获业务异常信息

    Spring Boot FeignClient 如何捕获业务异常信息

    这篇文章主要介绍了Spring Boot FeignClient 如何捕获业务异常信息的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝...

    lucax20397472021-09-19
  • Java教程Java实现多项式乘法代码实例

    Java实现多项式乘法代码实例

    今天小编就为大家分享一篇关于Java实现多项式乘法代码实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来...

    Czhenya7042021-06-08
  • Java教程SpringBoot使用Nacos动态配置数据源的方法

    SpringBoot使用Nacos动态配置数据源的方法

    这篇文章主要介绍了SpringBoot使用Nacos动态配置数据源的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参...

    bia!10152021-08-26
  • Java教程Java设计模式之java中介者模式详解

    Java设计模式之java中介者模式详解

    这篇文章主要为大家详细介绍了23种设计模式之java中介者模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助...

    大忽悠爱忽悠6062022-01-04