Java 8 Streams By Examples

Whenever we hear about Java 8 Streams the first thing which strike in mind would be Java I/O stream and classes like InputStream and OutputStream. But here in Java 8 Stream is quite different concept than Java I/O Streams. Java 8 Stream best implementation of functional programming which can be used easily with Java Collection Framework.

What is Stream in Java 8?

Stream in Java 8 can be considered as an expressive syntax structure which supports functional-style operations such as filter, map-reduce transformations on elements of collections. Stream can be defined as a chain of various functional operations on various data sources and Java Collection except java.util.Map.

Let’s have an example of it. We have one Employee class with Name and Salary Information.

class Employee{
    public String name;
    public int salary;
    
    public Employee(String name, int salary){
        this.name = name;
        this.salary = salary;
    }
}

We have to filter employees with salary greater than 100K, than sort all employees on salary in ascending order and print name and salary of filtered employees in sorted order.

//List of all Employees
List<Employee> empList = Arrays.asList(
    new Employee("Alice M. Albert",104800),
    new Employee("Thomas T. Duarte",111100),
    new Employee("Cory S. Gonsalves",116100),
    new Employee("Susan E. Evans",107200),
    new Employee("Samantha J. Peralta",116600),
    new Employee("Marilyn A. Williams",93100),
    new Employee("Jackeline C. Abeyta",100900),
    new Employee("Juan T. Young",106900),
    new Employee("Barbara J. Brown",114500),
    new Employee("Joseph C. Allred",114600),
    new Employee("Kristin F. Mahar",82000),
    new Employee("Tina J. Woods",114900),
    new Employee("Thomas J. Klein",99100),
    new Employee("Evelyn A. Shafer",101500),
    new Employee("James S. Lunsford",84100),
    new Employee("Christine A. Quinn",109900),
    new Employee("Manuela A. Bowling",98200),
    new Employee("Dean R. Roman",116400),
    new Employee("Yvonne D. Schultz",117700),
    new Employee("Al S. Mains",109300)
); 

Let’s try this in imperative style using Collection classes.

Collections.sort(empList, new Comparator<Employee>() {
    @Override
    public int compare(Employee e1, Employee e2) {
        return e1.salary - e2.salary;
    }
});

for(Employee e : empList){ 
    if(e.salary > 100000){ 
        System.out.println("Name : " + e.name+", Salary : " + e.salary); 
    }
}
Same code using Functional Style in Java 8
empList.stream() //Open a stream on List
    .filter(e -> e.salary > 100000)  //Find employees with Salary Higher than 100k
    .sorted((Employee e1, Employee e2) -> e1.salary - e2.salary) //Sort Employee from highest to lowest Salary
    .forEach(e -> System.out.println("Name : " + e.name+", Salary : " + e.salary)); //Print Employees in sorted order

Code using streams seems to be more expressive, compact and readable.

Important properties of Java 8 Streams

  • Streams are created from various sources like BufferedReader, Arrays, Lists, Sets etc. Majority of them are Collection classes
  • Stream operations are of two types,
    • Intermediate (Transformation)
    • Termination (Collection, Aggregation)
  • Streams carry values from data source to chained operations
  • Chained operations in a stream take lambda expression as an argument
  • Streams don’t have capabilities to store intermediate data
    • That means while applying any lambda function it doesn’t create new set of data. It just create chain of operations and execute the lambda expression if it is requested by termination operation
  • Streams supports Lazy evaluation
    • For example Stream is created from a List of 10 elements, there are 3 Intermediate operation, and as a Termination operation findFirst() method is placed. So rather than executing every Intermediate operation 10 times and giving first element final result. Stream will just identify the element by findFirst() method and execute all intermediate methods just once. This is called Lazy Evaluation.
  • Mostly Streams are considered to be immutable as majority the operations in Streams are stateless (Still it is dependent upon the programmer)
  • We can access first and/or next element from source as Streams are not supporting indexes
  • You can create Lists or Arrays from Streams as an output using Termination operation
  • Stream are not reusable after calling a termination operation.
  • Stream can also be wrapped around data sources which generate infinite elements

I hope this article would be add some value to you. Stay tuned for such more articles on Java 8.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>