Java 8 Stream Explained With Examples

Java 8 Stream Explained With Examples

If you want to perform some actions on a collections object for example: filtering, sorting or manipulating each element on that object based on some condition, you can use the java 8 stream feature to complete your requirement easily with less code.

It dosen't mean that you cannot achieve your requirement without Stream. But with Stream, it takes less lines of code to achieve your requirement and your program becomes more readable. Let us now try to understand the concept with some examples - 

Syntax

You can get a stream over a collection object using dot operator.

<collection object>.stream();

Example:

List<Integer> list = new ArrayList<Integer>();

list.stream();        //Returns a sequential Stream with this collection

Usage 

We can perform two major tasks on a collection object using stream

  • Filter
  • Map

Filter - 

If you want to filter a collection object (for example a list of string) based on some condition then you can use filter(Predicate<? super T> predicate) method on the stream of that object. This method takes a predicate and returns a stream of filtered list. But, what is this predicate? Actually, predicate is a functional interface (An interface that has only one abstract method) and you have to provide implementation of this interface as Lamda Expression to the filter method to process each element on the collection object based on this given implementation.

<collection object>.stream().filter(p -> <condition>);

Here, filter method checks each element p in the <collection object> based on given <condition> and return a stream of filtered list. Let us now look at some examples - 

Example : From a list of String, filter out only those strings that ends with character 'e'

package com.codemeright.stream;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class StreamFilterStringList{

    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("Code");
        list.add("Me");
        list.add("Right");

        // Before java 8 Stream it takes 4 to 5 lines of code
        List<String> listTemp = new ArrayList<String>();
        for (String s : list) {
            if (s.endsWith("e")) {
                listTemp.add(s);
            }
        }
        System.out.println(listTemp);

        // After java 8 Stream it takes only one line of code
        listTemp = list.stream().filter(s -> s.endsWith("e")).collect(Collectors.toList());
        System.out.println(listTemp);
    }
}

OUTPUT:

[Code, Me]

[Code, Me]

Here, we took 's' inside filter method, but earlier we took 'p' ? It's because 'p' is just a literal and you can take any valid literal in place of 'p' and using that literal you can provide your condition to filter the collection.

Map - 

If you want to change each and every element of a collection object then you can use map(Function<? super T, ? extends R> mapper) method on the stream of that object. This method takes a mapper and returns a stream of mapped list. Same as predicate,mapper is also a functional interface and you have to provide the implementation to the map function same as above.

<collection object>.stream().map(m -> <condition>);

Here, map method process each element m in the <collection object> based on given <condition> and return a stream of mapped list.

Example : In a list of Integer, multiply each Integer with 2

package com.codemeright.stream;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class StreamMapStringList {

    public static void main(String[] args) {

        List<Integer> list = new ArrayList<Integer>();
        list.add(10);
        list.add(25);
        list.add(30);
        list.add(35);
        list.add(40);
        list.add(45);
        list.add(50);

        // Before java 8 Stream it takes 4 to 5 lines of code
        List<Integer> listTemp = new ArrayList<Integer>();
        for (Integer i : list) {
            listTemp.add(i * 2);
        }
        System.out.println(listTemp);

        // After java 8 Stream it takes only one line of code
        listTemp = list.stream().map(p -> (p*2)).collect(Collectors.toList());
        System.out.println(listTemp);

    }

}

OUTPUT:

[20, 50, 60, 70, 80, 90, 100]

[20, 50, 60, 70, 80, 90, 100]

Here, output is same in both cases but the lines of code is reduced in second case due to stream.

Utility Methods

After getting the stream of filtered list or mapped list, you can call some utility methods on that stream like count, max, min, sorted and so on. Let us take a look at some of these in action -

Count

Returns the count of element in current stream.

package com.codemeright.stream;

import java.util.ArrayList;
import java.util.List;

public class StreamCount {

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(10);
        list.add(25);
        list.add(30);
        list.add(35);
        list.add(40);
        list.add(45);
        list.add(50);

        // Before java 8 Stream it takes 4 to 5 lines of code
        long count = 0;
        for (Integer i : list) {
            if (i % 2 == 0) {
                count++;
            }
        }
        System.out.println(count);

        // After java 8 Stream it takes only one line of code
        count = list.stream().filter(p -> (p % 2 == 0)).count();
        System.out.println(count);

    }

}

OUTPUT :

4
4

Sorted

Returns a stream of sorted list in default sorting order (Ascending). If you want a custom sorting order you can use overloaded method of sorted that takes a comparator.

package com.codemeright.stream;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class StreamMax {

    public static void main(String[] args) {

        List<Integer> l1 = new ArrayList<Integer>();
        l1.add(10);
        l1.add(25);
        l1.add(30);
        l1.add(35);
        l1.add(40);
        l1.add(45);
        l1.add(50);
        
        //Before java 8 (Without Stream)
        List<Integer> l2 = new ArrayList<Integer>();
        for(Integer i : l1) {
            if(!l2.contains(i)) {
                l2.add(i);
            }
        }
        System.out.println(l2);
        
        //After java 8 (With Stream)
        List<Integer> l3 = l1.stream().filter(p -> p > 10).sorted().collect(Collectors.toList());
        System.out.println(l3);
    }
}

Skip

Takes a long 'n' and returns a stream of a list containing the elements of current list after n elements, i.e. it skips first 'n' elements.

package com.codemeright.stream;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class StreamSkip {

    public static void main(String[] args) {

        List<Integer> l1 = new ArrayList<Integer>();
        l1.add(10);
        l1.add(25);
        l1.add(30);
        l1.add(35);
        l1.add(40);
        l1.add(45);
        l1.add(50);
        
        //Before java 8 (Without Stream)
        List<Integer> l2 = new ArrayList<Integer>();
        for(int i = 0; i < l1.size(); i++) {
            if(i > 2) {
                l2.add(l1.get(i));
            }
        }
        System.out.println(l2);
        
        //After java 8 (With Stream)
        List<Integer> l3 = l1.stream().skip(3).collect(Collectors.toList());
        System.out.println(l3);
    }
}

OUTPUT:

[35, 40, 45, 50]
[35, 40, 45, 50]

Conclusion

 The java 8 stream helps you reduce the size of your code and makes it more readable. Hence, it's recommended to use stream over old and ugly looping on collection objects.

ADVERTISEMENT

About  |  Privacy Policy  |  Disclaimer  |  © Copyright 2018. All Rights Reserved.