Gurinder
Gurinder

Reputation: 993

Java 8 Stream in main method

Someone asked me in an interview if we shoul write streaming operation in the main method.

Does it makes any difference?

For example:

class Athlete {

  private String name;
  private int id;

  public Athlete(String  name,int id) {
    this.name = name;
    this.id = id;
  }
}

public class Trial {

  public static void main(String[] args) {
    List<Athlete> list = new ArrayList<>();
    list.add(new Athlete("John", 1));
    list.add(new Athlete("Jim", 2));
    list.add(new Athlete("Jojo", 3));

    list.stream().forEach(System.out::print); // or any other any stream operation
  }
}

So I am just curious to know if it makes any difference... For now, the only thing I know is that once the stream is consumed, it cannot be consumed again.

So does it affect the memory or create buffer memory in the JVM for streaming?

If yes? Why should this not be used in the main method?

Upvotes: 0

Views: 462

Answers (2)

Holger
Holger

Reputation: 298469

The question whether “we should write streaming operation in the main method” is a loaded question. The first thing it implies, is the assumption that there was something special about the main method. Regardless of which operations we are talking about, if the conclusion is that you may or may not use them in an arbitrary method, there is no reason why you should come to a different conclusion when the method in question is the main method.

Apparently, “should we …” is meant to actually ask whether “should we avoid …”. If that’s the question, then, keeping in mind that there are no special rules for the main method, if there was a reason forbidding the use of the Stream API, that reason also applied to all other methods, making the Stream API an unusable API. Of course, the answer is that there is no reason forbidding the Stream API in the main method.


Regarding memory consumption, when replacing a for-each loop with a Collection.forEach method invocation, you are trading an Iterator instance for a lambda instance, so have no signifcant difference in the number and size of the created object instances. If you use Stream’s forEach method, you add a Spliterator and a Stream instance, which still can be considered insignificant, even when your application consists of the main method only. The memory pre-allocated by a JVM is much larger than the memory consumed by those few objects and your objects are very likely to fit within the threads’s local allocation store. In other words, from the outside of the JVM, there will be no difference in the memory used by the process.

As you mentioned the term “buffer”, the conceptual thing you should know is that a Stream does not buffer elements for most operations (including forEach), so, regardless of whether you traverse a Collection via loop or Stream, in both cases no memory scaling with the Collection’s size is ever allocated, so the difference, if any, remains as small as described above, regardless of whether you iterate over three elements as in your example or over three million elements.


On issue that could create confusion is that you should not use multi-threaded operations in a class initializer, which implies that you should not use a parallel stream in a class initializer. But that’s not forbidding Stream operations per se, further, the main method is not a class initializer; when the main method is invoked, the class has been initialized already.

Upvotes: 4

Hank D
Hank D

Reputation: 6481

In interview questions, don't assume that every yes/no question is limited to those two choices. A good answer might be "no difference either way".

In this case, they might have been looking for you to recognize that list.foreach() is more efficient than list.stream().foreach().

Upvotes: 2

Related Questions