Streams VS Collections in Java

In this lesson, we will explore some of the key differences between the Streams and Collections in Java.

Streams VS Collections

                                        Streams                                      Collections
  Can not add or modify elements. It’s a fixed dataset Can add or modify elements whenever we want
  Elements in a stream can be accessed only in sequence Elements in a collection can be accessed in any order
  Streams are traversable only once. Collections can be traversed multiple times.
  Streams are lazily constructed. Collections are eagerly constructed.
     

Examples

Example 1:

We can add or remove elements from collections, but we can’t do that from streams.

class Test {

  public static void main(String[] args) {
    List<String> list = new ArrayList<>();

    // Collections
    // add items
    list.add("item1");
    list.add("item2");

    // remove items
    list.remove("item2");

    // Streams
    list.stream() ... // we don't have any methods for adding or removing the elements from the stream
  }
}

Example 2:

We can iterate over elements of the collections as many times as we want, but we can iterate only once over the elements of the stream.

class Test {

  public static void main(String[] args) {
    List<String> names = new ArrayList<>(Arrays.asList("Steve", "Melissa", "Megan", "Joshua", "Alexander", "Jim", "Paul"));

    // iterate over collection - 1.
    for (String name : names) {
      System.out.print(name + " ");
    }

    System.out.println();

    // iterate over collection - 2.
    for (String name : names) {
      System.out.print(name + " ");
    }

    System.out.println();

    Stream<String> namesStream = names.stream();

    //iterate over a stream - 1.
    namesStream.forEach(name -> System.out.print(name + " "));

    System.out.println();

    //iterate over a stream - 2.
    namesStream.forEach(name -> System.out.println(name + " "));
  }
}

Output :

 
Steve Melissa Megan Joshua Alexander Jim Paul
Steve Melissa Megan Joshua Alexander Jim Paul
Steve Melissa Megan Joshua Alexander Jim Paul
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
  at java.base/java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
  at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
  at com.company.Test.main(User.java:36)

You see that we got an exception when we tried to iterate over a stream for the second time. The stream has been closed after the first iteration, so that we can use it only once.

Example 3:

All the elements get computed initially in collections, so we can say that the collections are eagerly constructed.

Streams are lazily constructed i.e intermediate operations are not evaluated until the terminal operation is invoked.

class Test {

  public static void main(String[] args) {
    List<String> names = new ArrayList<>(Arrays.asList("Steve", "Melissa", "Megan", "Joshua", "Alexander", "Jim", "Paul"));

    names.stream()
         .filter(name -> name.length() > 5)
         .limit(2)
         .forEach(System.out::println); // here, the strings are evaluated until the 2 strings with length > 5 are found.
  }
}

I hope this tutorial was helpful to you. To learn more, check out other Java Functional Programming tutorials.

 

Leave a Reply

Your email address will not be published. Required fields are marked *