堆栈使用 Java 8 集合流 API

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30387579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:02:29  来源:igfitidea点击:

Stack using the Java 8 collection streaming API

javajava-8java-streamjava-collections-api

提问by jbx

I have a method which generates an object each time I execute it, and I need to reverse the order with which I am getting them. So I thought the natural way to do it would be a Stack, since it is LIFO.

我有一个方法,每次执行它时都会生成一个对象,我需要颠倒获取它们的顺序。所以我认为最自然的方法是 Stack,因为它是 LIFO。

However, the Java Stackdoes not seem to play well with the new Java 8 streaming API.

但是,Java Stack似乎不能很好地与新的 Java 8 流 API 配合使用。

If I do this:

如果我这样做:

   Stack<String> stack = new Stack<String>();
   stack.push("A");
   stack.push("B");
   stack.push("C");

   List<String> list = stack.stream().collect(Collectors.toList());
   System.out.println("Collected: " + list);

The output I get is:

我得到的输出是:

Collected: [A, B, C]

Why isn't it outputing them in the expected LIFO order to the stream? Is this the right way to flush out all the items from the stack to a list in the right (LIFO) order?

为什么不以预期的 LIFO 顺序将它们输出到流?这是将堆栈中的所有项目以正确的 (LIFO) 顺序刷新到列表的正确方法吗?

回答by Zelldon

As already mentioned in the comments, we have well tested Dequeinterface which should be preferred.

正如评论中已经提到的,我们有经过良好测试的Deque界面,应该是首选。

But I will you give the reason why Stackshouldn't be used.

但我会告诉你为什么Stack不应该使用的原因。

At first, the Java Doc. of the Stack says itself:

首先,Java Doc。堆栈的自述:

A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class. For example:

Deque stack = new ArrayDeque();

Deque 接口及其实现提供了一组更完整和一致的 LIFO 堆栈操作,应优先使用此类。例如:

Deque stack = new ArrayDeque();

See JavaDoc.

请参阅JavaDoc

So what it is the problem with the Stackclass.

那么这个Stack类有什么问题。

Like Martin Fowler already mentioned in his book Refactoring: Improving the Design of Existing Codeat the refactoring method Replace Inheritance with Delegation, a Stack shouldn't inherit from a Vector.

就像 Martin Fowler 在他的《重构:改进现有代码的设计》一书中提到 的重构方法用委托替换继承一样,堆栈不应该从向量继承。

One of the classic examples of inappropriate inheritance is making a stack a subclass of vector. Java 1.1 does this in its utilities (naughty boys!) [6, p. 288]

不恰当继承的典型例子之一是将堆栈作为向量的子类。Java 1.1 在它的实用程序中做到了这一点(顽皮的孩子们!)[6, p. [288]

Instead, they should have used delegation like in the picture below, which is also from the book.

相反,他们应该使用如下图所示的委托,这也是本书中的。

See also here: Replace Inheritance with Delegation

另请参见此处:将继承替换为委托

Replace Inheritance with Delegation

用委托代替继承

So but why is this a problem:

那么,为什么这是一个问题:

Because the Stack has only 5 Methods:

因为 Stack 只有 5 个方法:

  1. pop
  2. push
  3. isEmpty
  4. search
  5. size

    size()and isEmpty()are inherited from the Vectorclass and the other methods from the Vectorare not used. But through the inheritance, other methods are forwarded to the Stackclass which makes no sense.

  1. 流行音乐
  2. 是空的
  3. 搜索
  4. 尺寸

    size()isEmpty()是从Vector类继承的,并且Vector不使用来自 的其他方法。但是通过继承,其他方法被转发到Stack类中,这是没有意义的。

And Fowler says to this problem:

福勒对这个问题说:

You can live with the situation and use convention to say that although it is a subclass, it's using only part of the superclass function. But that results in code that says one thing when your intention is something else—a confusion you should remove.

您可以接受这种情况并使用约定来说明尽管它是一个子类,但它仅使用了超类函数的一部分。但这会导致代码在你的意图是另一件事时说一件事——你应该消除这种混淆。

This hurts the Interface Segregation Principle

这损害了接口隔离原则

which says:

其中说:

CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DO NOT USE.

不应强迫客户依赖他们不使用的接口。



You can check out the source codeof the Vectorand Stackclass and you will see that the Stack class inherit the spliteratormethod and the VectorSpliteratorinnerClass from the Vectorclass.

可以查看VectorStack的源码,会看到Stack类继承了类的spliterator方法和VectorSpliteratorinnerClass Vector

This method is used by the Collectioninterface to impl. the default version of stream method:

Collection接口使用该方法来实现。流方法的默认版本:

default Stream<E> More ...stream() {
  return StreamSupport.stream(spliterator(), false);
}

So avoid simply the usage of the Vectorand Stackclass.

所以避免简单地使用VectorandStack类。

[6] Refactoring: Improving the Design of Existing Code Fowler, Martin year 1997

[6] 重构:改进现有代码 Fowler 的设计,Martin 1997 年