Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stack using the Java 8 collection streaming API

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<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?

like image 360
jbx Avatar asked May 22 '15 02:05

jbx


People also ask

What is the use of stream API in Java 8?

Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.

Which package is used for stream API in Java 8?

All the Java Stream API interfaces and classes are in the java. util. stream package.

What are the differences between collection and stream API in Java 8?

Differences between a Stream and a Collection: A stream does not store data. An operation on a stream does not modify its source, but simply produces a result. Collections have a finite size, but streams do not.

Does Java 8 support streams?

Java 8 offers the possibility to create streams out of three primitive types: int, long and double. As Stream<T> is a generic interface, and there is no way to use primitives as a type parameter with generics, three new special interfaces were created: IntStream, LongStream, DoubleStream.


1 Answers

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<Integer> stack = new ArrayDeque<Integer>(); 

See JavaDoc.

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.

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:

  1. pop
  2. push
  3. isEmpty
  4. search
  5. 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.

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 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<E> 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

like image 192
Zelldon Avatar answered Sep 18 '22 22:09

Zelldon