Stream API in Java 8

  JamesWarner        2018-01-30 00:14:46       4,020        0    

Overview

In this lesson on Stream API in Java, we will study how we can put Streams to use to write efficient and much more maintainable code. We will also write code with and without Streams so that we are able to compare the two versions.

Before doing all this, we must know how to create a Stream and process it and that is what we will get started with.

Introduction to Streams

We will be starting with creating Streams. Let us get started with the Stream<T> API which enables us to play with Stream processing.

Creating Streams

Streams can be created from any source like a Collection or an array. Let’s get started with some example by creating a stream from a List:

List<String> languages = Arrays.asList("German", "Hindi", "Sanskrit");
Stream<String> stream = languages.stream();

 

That was the easy part actually. Every collection have the stream(...) method to create a Stream. We just created a Stream from a List. Let’s try another example with Arrays:

String[] lang = new String[]{"French", "German", "Hindi"};

Stream<String> langStream = Arrays.stream(lang);

 

Almost the same actually.

Type of operations on Streams

There are two kind of operations which can be performed on a Stream. They are:

  • Terminal Operations: These operations doesn’t modify the original source of data or process it. In any manner, a new Stream isn’t created to reach the objective. One such example is a count operation:

long distinctCount = list.stream().distinct().count();

In above example, we created a stream of distinct elements and counted them. To count the elements, we didn’t have to create a new Stream.

  • Intermediate Operations: These operations does modify the original source of data. In the last example we showed, the distinct() method represents an intermediate operation and so, it created a new list of distinct elements.

Iterating Collections

Stream API is utterly helpful when it comes to write clean code to iterate over a Collection and apply some logic.

Like, what if you want to identify if an element is present in a list or not. Let’s do this using a foreach loop:

for (String num : integers)

{

    if (string.contains(3)) {

        return true;

    }

}

That was pretty much straightforward. Now, let’s try doing the same using Streams:

boolean doesExist = integers.stream().anyMatch(num -> num.contains(3));

Filtering Collections

To filter a collection, we can also provide Streams a predicate to satisfy. Only the elements which satisfy the predicate remains in the collection.

 

Here is an example code snippet:

 

ArrayList<Integer> integers = new ArrayList<>();

integers.add(1);

integers.add(2);

integers.add(3);

integers.add(4);

integers.add(5);

integers.add(6);

integers.add(7);



Stream<Integer> stream = integers.stream().filter(element -> element % 2 == 0);

stream.forEach(System.out::println);

 

The output for above program would be:

2

4

6

Of course, only even elements remained in the original list, so, filter(...) method is an Intermediate operation.

Mapping with Streams

When we need to populate a Collection on the basis of another collection and conditions, we can use the map(...) method. Let us try this with a code snippet:

List<String> strings = new ArrayList<>();

strings.add("1");

strings.add("2");

strings.add("3");

Stream<Integer> stream = strings.stream().map(Integer::valueOf);

Above code snippet converts a list of Strings into a list of Integers using map(...) method after parsing them.

Collecting elements with Streams

Now, we can modify elements of a Collection without affecting the original java development source and collect the modified data in a separate collection using the collect(...) method:

 

List<String> languages = Arrays.asList("French", "German", "Hindi", "Sanskrit");

List<String> resultList = languages.stream().map(String::toUpperCase).collect(Collectors.toList());

resultList.forEach(System.out::println);

 

The output of this code will be:

FRENCH

GERMAN

HINDI

SANSKRIT

 

So, we just collected elements from one list, modified it and collected the results into another list.

 

When is a Stream considered consumed

A stream is considered as consumed when a terminal operation is done executing. It is worth noting that more than one intermediate operations are not supposed to be executed on the same Stream instance.

 

When we need to perform parallel intermediate operations:

 

public void multipleIntermediate() {

    Stream<Integer> integers = Stream.of(1.1, 2.2, 3.3);

    integers = integers.filter(d -> d > 2);

    integers.filter(d -> d > 3).forEach(System.out::println);

}

 

Conclusion

In this lesson on Stream API in Java 8, we discussed about what they are, how are they made, what use they are of and what purpose do they actually achieve. We compared some code about how they would have looked without the Stream API as well. Streams make our work easy and our code clean, what else we need!!

 

DEVELOPMENT  TEAM  JAVA 8  STREAM API 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

Truth about project manager