jbx*_*jbx 19 java java-8 java-stream java-collections-api
我有一个方法,每次执行它时都会生成一个对象,我需要颠倒我获取它们的顺序.所以我认为这样做的自然方式就是Stack,因为它是LIFO.
但是,Java Stack似乎不能很好地与新的Java 8流API一起使用.
如果我这样做:
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);
Run Code Online (Sandbox Code Playgroud)
我得到的输出是:
Collected: [A, B, C]
Run Code Online (Sandbox Code Playgroud)
为什么不以预期的LIFO顺序将它们输出到流中?这是将所有项目从堆栈清除到右(LIFO)顺序列表的正确方法吗?
Zel*_*don 34
正如评论中已经提到的,我们有一个经过良好测试的Deque界面,应该是首选.
但我会告诉你为什么Stack不应该使用它.
首先,Java Doc.堆栈说自己:
Deque接口及其实现提供了更完整和一致的LIFO堆栈操作集,应优先使用此类.例如:
Deque stack = new ArrayDeque();
请参阅JavaDoc.
这就是Stack课堂上的问题.
就像Martin Fowler在他的" 重构:改进现有代码的设计"一书中已经提到的那样 ,在重构方法中将继承替换为委托,Stack不应该从Vector继承.
不适当继承的一个典型例子是使堆栈成为vector的子类.Java 1.1在它的实用程序(顽皮的男孩!)中做到了这一点[6,p.288]
相反,他们应该使用如下图所示的委托,这也来自书中.
另请参见:使用委派替换继承

那么为什么这是一个问题:
因为Stack只有5个方法:
福勒对这个问题说:
你可以忍受这种情况并使用约定来说虽然它是一个子类,但它只使用了超类函数的一部分.但是这导致代码在你的意图是其他东西时说了一件事 - 你应该删除的混乱.
这会损害接口隔离原则
其中说:
客户不应强制依赖他们不使用的接口.
您可以查看Vector和Stack类的源代码,您将看到Stack类从类继承spliterator方法和VectorSpliteratorinnerClass Vector.
这个方法被Collection接口用于impl.stream方法的默认版本:
default Stream<E> More ...stream() {
return StreamSupport.stream(spliterator(), false);
}
Run Code Online (Sandbox Code Playgroud)
所以要避免简单地使用Vector和Stack类.
[6]重构:改进现有代码福勒的设计,Martin 1997年
| 归档时间: |
|
| 查看次数: |
9267 次 |
| 最近记录: |