首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Java 8集合流API的堆栈

使用Java 8集合流API的堆栈
EN

Stack Overflow用户
提问于 2015-05-22 10:45:22
回答 1查看 14.5K关注 0票数 28

我有一个方法,每次我执行它时都会生成一个对象,我需要颠倒获取它们的顺序。所以我认为最自然的方式应该是堆栈,因为它是后进先出的。

然而,Java似乎不能很好地与新的Java8流Stack配合使用。

如果我这样做:

代码语言:javascript
复制
   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);

我得到的输出是:

代码语言:javascript
复制
Collected: [A, B, C]

为什么它没有按照预期的后进先出顺序将它们输出到流中?这是以正确的(LIFO)顺序将堆栈中的所有项刷新到列表中的正确方式吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-22 14:36:32

正如评论中已经提到的,我们已经对Deque接口进行了很好的测试,这应该是首选的。

但是我会给你一个不应该使用Stack的理由。

首先,Java文档。堆栈本身就说明了问题:

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

去队列堆栈=新的ArrayDeque();

参见JavaDoc

那么Stack类的问题是什么呢?

就像Martin Fowler在他的书 refactoring : Improving the Design of Existing Code at the refactoring method Replace Inheritance with Delegation中提到的那样,栈不应该继承自。

是不适当继承的经典例子之一,它使堆栈成为vector的子类。Java1.1在它的实用程序中做到了这一点(淘气的男孩!) 6,第288页

相反,他们应该像下面的图片一样使用委托,这也是本书中的内容。

另请参阅此处:Replace Inheritance with Delegation

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

因为堆栈只有5个方法:

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

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

福勒对这个问题说:

你可以接受这种情况,并使用约定来说明,虽然它是一个子类,但它只使用了超类函数的一部分。

。但这会导致代码在你的意图是其他东西时说明一件事--这是你应该消除的困惑。

这会伤害Interface Segregation Principle

上面写着:

不应强制

客户端依赖于它们不使用的接口。

Stack您可以查看VectorStack类的源代码Stack,您将看到Stack类从Vector类继承了spliterator方法和VectorSpliterator innerClass。

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

代码语言:javascript
复制
default Stream<E> stream() {
  return StreamSupport.stream(spliterator(), false);
}

因此,避免简单地使用VectorStack类。

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

票数 49
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30387579

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档