Java堆栈

时间:2020-01-09 10:35:49  来源:igfitidea点击:

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的元素。你可以通过调用stackiterator()方法来获得一个迭代器。这是一个从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非常相似。