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

简介: 总之,虽然在日常开发中,`java.util.Stack`正逐渐被其他类如 `Deque`接口的实现所取代,但手写一个栈(无论是基于数组还是链表)都是一次很好的编程练习,它可以帮助开发者更加深入地理解栈这种数据结构的工作原理和各种操作。

在Java集合框架中,Stack类是一个后入先出(LIFO)的堆栈,但在现代的Java开发中,这个类往往被 Deque接口的实现类(如 LinkedListArrayDeque)所替代。不过,手写一个栈结构不仅是对数据结构理解的一种体现,也是检验编程能力的一个很好的例子。

为了实现一个基础的栈,我们可以使用数组或链表作为内部存储结构。以下是使用数组实现的一个简单的栈结构,考虑到易懂和实用性,我会展示一个简易版本的栈实现,它将支持基本的操作:压栈(push)、弹栈(pop)、查看栈顶元素(peek)和检查栈是否为空(isEmpty)。首先,我们定义栈的数据结构如下:

public class CustomStack<E> {
    private Object[] array;
    private int size;
    private static final int DEFAULT_CAPACITY = 10;

    public CustomStack() {
        array = new Object[DEFAULT_CAPACITY];
        size = 0;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public E peek() {
        if (isEmpty()) {
            throw new EmptyStackException();
        }
        return (E) array[size - 1];
    }

    public E pop() {
        E element = peek();
        array[--size] = null; // 防止内存泄漏
        return element;
    }

    public void push(E item) {
        ensureCapacity();
        array[size++] = item;
    }

    private void ensureCapacity() {
        if (size >= array.length) {
            int newSize = array.length * 2;
            array = Arrays.copyOf(array, newSize);
        }
    }

    // 更多实用方法(例如返回栈的大小,遍历等)可以根据需要增加
}

在这个 CustomStack类中,我们使用了泛型来提供类型安全,并且内部使用了一个 Object类型的数组来存储栈中的元素。数组的初始化大小为 DEFAULT_CAPACITY,这是我们预设的一个值,在数组容量不够时,通过 ensureCapacity方法进行扩容。

push方法将元素压入栈,并在必要时增加数组的大小。pop方法从栈中移除顶部元素并返回这个元素,该方法在执行之前会调用 peek方法来确保栈不为空,并获取栈顶元素。

这种简单的栈实现在功能上可能与 java.util.Stack类类似,但它避免了继承自 Vector类的 java.util.Stack带来的线程同步开销。在多线程环境下,我们需要关注线程安全的问题,java.util.Stack是线程同步的,如果不需要这个特性,使用我们自己的 CustomStack会更高效。

如果需要使用链表来手写栈,则可以创建一个节点类来代表链表的节点,然后在栈类中使用这些节点来存储信息。链表实现的栈可以避免数组实现时的数组扩容操作,从而提高操作的效率。

总之,虽然在日常开发中,java.util.Stack正逐渐被其他类如 Deque接口的实现所取代,但手写一个栈(无论是基于数组还是链表)都是一次很好的编程练习,它可以帮助开发者更加深入地理解栈这种数据结构的工作原理和各种操作。

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