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.
However, the Java Stack does not seem to play well with the new Java 8 streaming API.
If I do this:
Stack stack = new Stack();
stack.push("A");
stack.push("B");
stack.push("C");
List 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?
解决方案
As already mentioned in the comments, we have well tested Deque interface which should be preferred.
But I will you give the reason why Stack shouldn't be used.
At first, the Java Doc. of the Stack says itself:
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();
So what it is the problem with the Stack class.
Like Martin Fowler already mentioned in his book
Refactoring: Improving the Design of Existing Code
at the refactoring method Replace Inheritance with Delegation,
a Stack shouldn't inherit from a Vector.
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]
Instead, they should have used delegation like in the picture below,
which is also from the book.

So but why is this a problem:
Because the Stack has only 5 Methods:
pop
push
isEmpty
search
size
size() and isEmpty() are inherited from the Vector class and the other methods from the Vector are not used. But through the inheritance, other methods are forwarded to the Stack class which makes no sense.
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.
which says:
CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DO
NOT USE.
You can check out the source code of the Vector and Stack class
and you will see that the Stack class inherit the spliterator method
and the VectorSpliterator innerClass from the Vector class.
This method is used by the Collection interface to impl. the default version of stream method:
default Stream More ...stream() {
return StreamSupport.stream(spliterator(), false);
}
So avoid simply the usage of the Vector and Stack class.
[6] Refactoring: Improving the Design of Existing Code Fowler, Martin
year 1997
本文探讨了Java中Stack类与Java 8 Stream API之间的不兼容性问题,并提出使用Deque接口作为替代方案来实现LIFO操作。文章还深入分析了Stack类的设计缺陷及其不当继承自Vector类的问题。
160

被折叠的 条评论
为什么被折叠?



