Java集合之Stack 源码分析 泽…

本文深入探讨了Java中栈(Stack)的数据结构实现原理,包括其继承结构、关键方法的源码解读及其工作流程。通过具体示例展示了如何使用Stack类,并详细分析了栈的基本操作如push、pop、peek等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


原文地址:http://www.tuicool.com/articles/YZZfA3y
1.简介

栈是数据结构中一种很重要的数据结构类型,因为栈的后进先出功能是实际的开发中有很多的应用场景。Java API中提供了栈(Stacck)的实现,简单使用如下所示

package com.test.collections;

import java.util.Stack;

public class StackTest {

  
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Stack stack = new Stack();
    stack.add("China");
    stack.add("Japan");
    stack.add("Russia");
    stack.add("England");
    
    System.out.println(stack.size()+"<="+stack.capacity());
    System.out.println(stack.elementAt(0));
    System.out.println(stack.get(0));
    System.out.println(stack.peek());
    System.out.println(stack.push("France"));
    System.out.println(stack.pop());
    System.out.println(stack.iterator());
    System.out.println(stack.empty());
    System.out.println(stack.isEmpty());
         System.out.println(stack.search("Russia"));
  }

}

2.继承结构

Stack类继承了Vector类,而Vector类继承了AbstractList抽象类,实现了List接口,Cloneable接口,RandomAcces接口以及Serializable接口,需要指出的Vector内部还有两个内部类ListItr和Itr,Itr在继承Vector的同时实现了Iterator接口,而ListItr在继承了Itr类的同时实现了ListIterator接口。

3.源码解读

通过Stack类发现含有的方法有pop(),peek(),push(Object),search(Object),empty()方法,其他值的方法是从Vector类继承而来,通过源码可以发现Vector有几个属性值: protected Object[] elementData , protected int elementCount ;protected int capacityIncrement private static final int MAX_ARRAY_SIZE = 2147483639 ;通过这几属性我们可以发现,Stack底层是采用数组来实现的,elementData用于保存Stack中的每个元素;elementCount用于动态的保存元素的个数,capacityIncrement用来保存Stack的容量(一般情况下应该是大于elementCount);MAX_ARRAY_SIZE 用于限制Stack能够保存的最大值数量。

a.removeElementAt()
public synchronized void removeElementAt(int paramInt) {
    this.modCount += 1;
    if (paramInt >= this.elementCount)
      throw new ArrayIndexOutOfBoundsException(paramInt + " >= "
          + this.elementCount);
    if (paramInt < 0)
      throw new ArrayIndexOutOfBoundsException(paramInt);
    int i = this.elementCount - paramInt - 1;
    if (i > 0)
      System.arraycopy(this.elementData, paramInt + 1, this.elementData,
          paramInt, i);
    this.elementCount -= 1;
    this.elementData[this.elementCount] = null;
  }
removeElementAt()方法用于移除某个位置的元素,需要指出元素的位置,这个方法来之与Stack的父类Vector;通过代码我们可以发现它的实现是首先判断参数是否合法然后将这个位置前的所有元素都向后移动了一位,而且把元素的个数-1,最后把原来位置最上面的那个元素置为空,从而实现了删除某个元素的操作。


b:elementData(int)


E elementData(int paramInt) {
    return this.elementData[paramInt];
  }

elementData(int)返回某一位置的元素的具体值,通过这个方面也可以看出Stack底层是有一个数组来实现的 。

c:elementAt(int)
public synchronized E elementAt(int paramInt) {
    if (paramInt >= this.elementCount)
      throw new ArrayIndexOutOfBoundsException(paramInt + " >= "
          + this.elementCount);
    return elementData(paramInt);
  }

elementAt(int paramInt)首先判断参数是否合法,然后就直接调用elementData(paramInt)返回具体的对象值。

d:peek()
public synchronized E peek() {
    int i = size();
    if (i == 0)
      throw new EmptyStackException();
    return elementAt(i - 1);
  }

通过源码就可以发现peek()只是获取了第一个位置的元素的值(Stack的下标和数组保持一致都是从0开始,最大到元素总数-1)

e:pop()

public synchronized E pop() {
    int i = size();
    Object localObject = peek();
    removeElementAt(i - 1);
    return localObject;
  }

pop()方法的实现是首先获取Stack的元素数量,然后调用peek()方法获取栈顶的第一个元素,然后调用removeElementAt(int)删除栈顶元素,最后将元素的值返回。

f:addElement(E paramE)
public synchronized void addElement(E paramE) {
    this.modCount += 1;
    ensureCapacityHelper(this.elementCount + 1);
    this.elementData[(this.elementCount++)] = paramE;
  }

addElement(E)方法是个很重要的方法,因为它实现了元素的添加。它在添加元素的时候首先将modCount加1,ensureCapacityHelper()主要用于保障Stack的容量,如果超过当前容量则调用grow()方法进行容量增加,如果操作最大的容量MAX_ARRAY_SIZE就会抛出异常。第三步才会实现元素的添加,就是i将该元素添加到栈顶,并且将元素的数目加1;

g:search(Object)
public synchronized int search(Object paramObject) {
    int i = lastIndexOf(paramObject);
    if (i >= 0)
      return (size() - i);
    return -1;
  }

该方法返回所查找对象所处的位置,如果不存在在返回-1;通过代码可以发现它的实现过程是这样的,首先通过lastLindexOf(Object)方法返回从栈底到栈顶最下面的的那个元素的下标,然后利用元素的总数目减去所处的下标就得到了元素的位置(),并且返回否则返回-1;(需要注意的改位置返回的是从栈顶到栈底开始所处的位置,栈顶元素的位置为1)

h:empty()
public boolean empty() {
    return (size() == 0);
  }

直接返回元素的数目与0比较的关系,size()方法是通过this.elementCount返回了栈元素的数目。

4.其他(小结)

通过源码我们可以看到Vector底层是一个数组,说明Stack的实现是通过数组来实现的,然后通过对数组的操作来模仿栈的各种功能。而且在源码中Vector的很多方法都是synchronized 的,也就是说是线程安全,所以说在多线程中是可以安全使用的,不过这样效率上肯定是会降低的。

内容概要:本文深入探讨了Kotlin语言在函数式编程和跨平台开发方面的特性和优势,结合详细的代码案例,展示了Kotlin的核心技巧和应用场景。文章首先介绍了高阶函数和Lambda表达式的使用,解释了它们如何简化集合操作和回调函数处理。接着,详细讲解了Kotlin Multiplatform(KMP)的实现方式,包括共享模块的创建和平台特定模块的配置,展示了如何通过共享业务逻辑代码提高开发效率。最后,文章总结了Kotlin在Android开发、跨平台移动开发、后端开发和Web开发中的应用场景,并展望了其未来发展趋势,指出Kotlin将继续在函数式编程和跨平台开发领域不断完善和发展。; 适合人群:对函数式编程和跨平台开发感兴趣的开发者,尤其是有一定编程基础的Kotlin初学者和中级开发者。; 使用场景及目标:①理解Kotlin中高阶函数和Lambda表达式的使用方法及其在实际开发中的应用场景;②掌握Kotlin Multiplatform的实现方式,能够在多个平台上共享业务逻辑代码,提高开发效率;③了解Kotlin在不同开发领域的应用场景,为选择合适的技术栈提供参考。; 其他说明:本文不仅提供了理论知识,还结合了大量代码案例,帮助读者更好地理解和实践Kotlin的函数式编程特性和跨平台开发能力。建议读者在学习过程中动手实践代码案例,以加深理解和掌握。
内容概要:本文深入探讨了利用历史速度命令(HVC)增强仿射编队机动控制性能的方法。论文提出了HVC在仿射编队控制中的潜在价值,通过全面评估HVC对系统的影响,提出了易于测试的稳定性条件,并给出了延迟参数与跟踪误差关系的显式不等式。研究为两轮差动机器人(TWDRs)群提供了系统的协调编队机动控制方案,并通过9台TWDRs的仿真和实验验证了稳定性和综合性能改进。此外,文中还提供了详细的Python代码实现,涵盖仿射编队控制类、HVC增强、稳定性条件检查以及仿真实验。代码不仅实现了论文的核心思想,还扩展了邻居历史信息利用、动态拓扑优化和自适应控制等性能提升策略,更全面地反映了群体智能协作和性能优化思想。 适用人群:具备一定编程基础,对群体智能、机器人编队控制、时滞系统稳定性分析感兴趣的科研人员和工程师。 使用场景及目标:①理解HVC在仿射编队控制中的应用及其对系统性能的提升;②掌握仿射编队控制的具体实现方法,包括控制器设计、稳定性分析和仿真实验;③学习如何通过引入历史信息(如HVC)来优化群体智能系统的性能;④探索中性型时滞系统的稳定性条件及其在实际系统中的应用。 其他说明:此资源不仅提供了理论分析,还包括完整的Python代码实现,帮助读者从理论到实践全面掌握仿射编队控制技术。代码结构清晰,涵盖了从初始化配置、控制律设计到性能评估的各个环节,并提供了丰富的可视化工具,便于理解和分析系统性能。通过阅读和实践,读者可以深入了解HVC增强仿射编队控制的工作原理及其实际应用效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值