Java集合篇之逐渐被遗忘的Stack,手写一个栈你会吗?

简介: Java集合篇之逐渐被遗忘的Stack,手写一个栈你会吗?

写在开头

其实在List的继承关系中,除了ArrayList和LinkedList之外,还有另外一个集合类stack(栈),它继承自vector,线程安全,先进后出,随着Java并发编程的发展,它在很多应用场景下被逐渐替代,成为了Java的遗落之类。不过,stack在数据结构中仍有一席之地,因此,我们有必要也应该好好的学一下!

Collection和Collections的区别?

在开始学习栈之前,先来解决一下之前一个网友在评论区问的问题:

Collection和Collections有什么区别?

虽然这两个类都在java.util包下,虽然只有一字之差,但它们的差别还是挺大的!
Collection 是JDK中集合层次结构中的最根本的接口。定义了集合类的基本方法。源码中的解释:

 * The root interface in the <i>collection hierarchy</i>.  A collection
 * represents a group of objects, known as its <i>elements</i>.  Some
 * collections allow duplicate elements and others do not.  Some are ordered
 * and others unordered.  The JDK does not provide any <i>direct</i>
 * implementations of this interface: it provides implementations of more
 * specific subinterfaces like <tt>Set</tt> and <tt>List</tt>.  This interface
 * is typically used to pass collections around and manipulate them where
 * maximum generality is desired.

Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法,不能实例化,Collection 集合框架的工具类。源码中的解释:

* This class consists exclusively of static methods that operate on or return
* collections.  It contains polymorphic algorithms that operate on
* collections, "wrappers", which return a new collection backed by a
* specified collection, and a few other odds and ends.

stack(栈)

栈(stack)是一种先进后出(Last In First Out,LIFO)的数据结构,类比于现实生活中的子弹上膛、泡泡圈。栈具有两个基本操作:入栈(push)和出栈(pop)。入栈表示将元素放入栈顶,而出栈表示从栈顶取出元素。

动图图解-入栈(push)
image.png

动图图解-出栈(pop)
image.png

在Java的工具包中其实帮我们封装好了一个类,java.util.Stack,它所提供的方法并不多,我们通过一个小示例感受一下。

【代码示例1】

Stack<String> stacks = new Stack<>();
//push方法入栈
 stacks.push("开");
 stacks.push("工");
 stacks.push("大");
 stacks.push("吉");
 stacks.push("!");
 System.out.println(stacks);
 //pop栈顶元素出栈
 String pop = stacks.pop();
 System.out.println(pop);
 //查看栈顶元素
 String peek = stacks.peek();
 System.out.println(peek);
 //判断堆栈是否为空
 boolean empty = stacks.empty();
 System.out.println(empty);
 //查看元素在堆栈中的位置
 int index = stacks.search("开");
 System.out.println(index);

输出:

[,,,,]
!
吉
false
4

手写一个stack(堆栈)

通过上面的代码示例我们了解了一个栈所具备的功能特点,根据它的特点,我们尝试一下手写一个栈!
首先,准备一个数组用来存储元素,可以定义为Object,这样支持多数据类型,我们这里直接选用int类型的好嘞。
自定义栈-源码:

/**
 * @ClassName Stack
 * @Description 手写一个int类型的堆栈
 * @Author hzm
 * @Date 2024/2/18 14:21
 * @Version 1.0
 */
public class Stack {
   
   
    private int arr[];
    private int top;
    private int capacity;

    /**
     * 提供一个有参构造,初始化栈
     * @param size
     */
    public Stack(int size) {
   
   
        this.arr = new int[size];
        this.top = -1;
        this.capacity = size;
    }

    /**
     * 入栈
     * @param p
     */
    public void push(int p) {
   
   
        if (isFull()) {
   
   
            System.out.println("堆栈空间溢出\n程序终止\n");
            System.exit(1);
        }

        System.out.println("入栈:" + p);
        arr[++top] = p;
    }

    /**
     * 出栈
     * @return
     */
    public int pop() {
   
   
        if (isEmpty()) {
   
   
            System.out.println("空栈,不可POP");
            System.exit(1);
        }
        return arr[top--];
    }

    /**
     * 判断栈是否已满
     * @return
     */
    public Boolean isFull() {
   
   
        return top == capacity - 1;
    }

    /**
     * 判断栈是否为空
     * @return
     */
    public Boolean isEmpty() {
   
   
        return top == -1;
    }

    /**
     * 遍历栈内元素
     */
    public void printStack() {
   
   
        for (int i = 0; i <= top; i++) {
   
   
            System.out.println(arr[i]);
        }
    }

    /**
     * 返回栈的大小
     * @return
     */
    public int size() {
   
   
        return top + 1;
    }

    /**
     * 查看栈顶元素
     * @return
     */
    public void peek(){
   
   
        System.out.println("栈顶元素:" + arr[top]);
    }
}

测试类中调用手写的这个stack:

public class Test {
   
   
    public static void main(String[] args) {
   
   
        Stack stack = new Stack(5);
        //入栈
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);
        //出栈
        int pop = stack.pop();
        System.out.println("出栈:"+ pop);
        //查看栈的大小
        int size = stack.size();
        System.out.println("栈容量:" + size);
        //查看栈顶元素
        stack.peek();
        //打印栈内元素
        stack.printStack();
    }
}

输出:

入栈:1
入栈:2
入栈:3
入栈:4
入栈:5
出栈:5
栈容量:4
栈顶元素:4
1
2
3
4

好了,今天的栈内容就写到这里吧,大家私下里可以找找leetcode上关于栈的算法题做做,深刻感受一下哈!

结尾彩蛋

如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥!

image.png

目录
相关文章
|
26天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
27 2
|
1月前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
26天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
1月前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
44 4
|
1月前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
1月前
|
Java 开发者
|
1月前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
28 0
|
20天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
11天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####