Java堆栈
Java Stack类java.util.Stack是一种经典的堆栈数据结构。我们可以将元素推到Java堆栈的顶部,然后再次弹出它们,这意味着从堆栈的顶部读取和删除元素。
JavaStack
类实际上实现了Java List接口,但是我们很少将Stack
用作List
,除非我们可能需要检查当前存储在栈中的所有元素。
请注意,Java Stack类是Vector的子类,Vector是同步的旧Java类。这种同步增加了对堆栈所有方法的调用的少量开销。此外,Vector类使用Java的多个较旧的部分(不再推荐),例如由Iterator接口取代的Enumeration。如果要避免这些问题,可以使用Java Deque作为堆栈。
Java 堆栈
"堆栈"是一种数据结构,我们可以其中将元素添加到堆栈的"顶部",然后再次从顶部移除元素。这也称为"后进先出(LIFO)"原则。相反,Java队列使用"先进先出(FIFO)"原理,将元素添加到队列的末尾,然后从队列的开头除去。
创建堆栈
要使用Java Stack,必须首先创建Stack类的实例。这是创建Java Stack实例的示例:
Stack stack = new Stack();
创建具有通用类型的堆栈
我们可以在Stack上设置通用类型,以指定Stack实例可以包含的对象的类型。声明Stack变量时,可以指定堆栈类型。这是创建具有通用类型的Java Stack的示例:
Stack<String> stack = new Stack<String>();
上面创建的堆栈只能包含String实例。
建议在Stack实例上使用通用类型,因为这会简化代码(访问Stack上的对象时无需强制转换),并降低了将错误类型的对象压入Stack的风险。
将元素推入堆栈
一旦有了JavaStack
实例,就可以将元素推到Stack
的顶部。推送到"堆栈"上的元素必须是Java对象。因此,实际上是将对象推入"堆栈"。
我们可以使用其push()方法将元素推入Java Stack中。这是将元素(对象)压入Java Stack的示例:
Stack<String> stack = new Stack<String>(); stack.push("1");
这个Java示例将带有文本" 1"的Java字符串压入"堆栈"。然后将字符串" 1"存储在"堆栈"的顶部。
堆栈中的流行元素
将元素推入Java堆栈后,我们可以再次从堆栈中弹出该元素。一旦从"堆栈"弹出一个元素,该元素就会从"堆栈"中删除。然后,"堆栈"的顶部元素就是紧随元素弹出之前被压入"堆栈"的任何元素。
使用pop()方法将元素从Java Stack中弹出。这是一个使用pop()
方法从Stack
中弹出一个元素的例子:
Stack<String> stack = new Stack<String>(); stack.push("1"); String topElement = stack.pop();
一旦将元素从"堆栈"中弹出,该元素就不再存在于"堆栈"中。
窥视堆栈的顶部元素
JavaStack
类有一个名为peek()
的方法,它使我们能够看到Stack
上的顶部元素是什么,而不会弹出该元素。这是一个窥视JavaStack
顶部的示例:
Stack<String> stack = new Stack<String>(); stack.push("1"); String topElement = stack.peek();
在运行这个Java示例之后,topElement变量将包含字符串对象1,该对象在调用peek()之前被推到Stack上。调用peek()
之后,String对象仍然存在于Stack
上。
搜索堆栈
我们可以使用search()方法在堆栈上搜索对象以获取其索引。在"堆栈"上的每个对象上调用该对象的" equals()"方法,以确定搜索到的对象是否在"堆栈"上。我们获得的索引是从"堆栈"顶部开始的索引,这意味着"堆栈"的顶部元素具有索引1.
这是我们在"堆栈"中搜索对象的方式:
Stack<String> stack = new Stack<String>(); stack.push("1"); stack.push("2"); stack.push("3"); int index = stack.search("3"); //index = 3
堆叠尺寸
我们可以通过Stacksize()
方法获得Java堆栈的大小,即当前存储在堆栈上的元素数。这是一个通过它的size()
方法获取Java堆栈大小的示例:
Stack<String> stack = new Stack<String>(); stack.push("1"); stack.push("2"); stack.push("3"); int size = stack.size();
运行此代码后,size
变量将包含值3,因为示例中的Stack在调用其size()
方法时包含3个元素。
迭代堆栈元素
我们可以通过从Stack中获取Java迭代器来迭代Java Stack的元素。你可以通过调用stack
iterator()方法来获得一个迭代器。这是一个从JavaStack
获取Iterator
并对其进行迭代的示例:
Stack<String> stack = new Stack<String>(); stack.push("123"); stack.push("456"); stack.push("789"); Iterator iterator = stack.iterator(); while(iterator.hasNext()){ Object value = iterator.next(); }
使用流处理堆栈
也可以通过Java Stream API处理Java Stack上的元素。为此,我们首先要通过" stream()"方法从"堆栈"中获取"流"。
一旦从Stack中获取了Stream,就可以处理流中的元素。这是从"堆栈"中获取"流"并处理元素的示例:
Stack<String> stack = new Stack<String>(); stack.push("A"); stack.push("B"); stack.push("C"); Stream stream = stack.stream(); stream.forEach((element) -> { System.out.println(element); // print element });
注意,该示例使用Java Lambda作为Stream.forEach()方法的参数。 lambda只是将元素打印到System.out
中
使用堆栈的反向列表
我们可以使用JavaStack
来反转Java列表。为此,我们可以将List中的所有元素压入Stack,从索引为0的元素开始,再依次为1等。从List中删除每个元素,然后压入Stack。一旦所有元素都在"堆栈"上,就可以将元素逐一弹出,然后将其添加回空白列表中。这是一个使用Java Stack反转Java List的示例:
List<String> list = new ArrayList<String>(); list.add("A"); list.add("B"); list.add("C"); System.out.println(list); Stack<String> stack = new Stack<String>(); while(list.size() > 0) { stack.push(list.remove(0)); } while(stack.size() > 0){ list.add(stack.pop()); } System.out.println(list);
使用Java双端队列作为堆栈
如本Java Stack教程顶部所述,我们也可以将Java Deque用作堆栈。 Java Deque教程还显示了如何做到这一点,但在这里我还将向我们展示一个简短的示例:
Deque<String> dequeAsStack = new ArrayDeque>String>(); dequeAsStack.push("one"); dequeAsStack.push("two"); dequeAsStack.push("three"); String one = dequeAsStack.pop(); String two = dequeAsStack.pop(); String three = dequeAsStack.pop();
如我们所见,它看起来与使用常规Java Stack非常相似。