Java Stream

Introduction

In Java, Stream is a sequence of elements supporting sequential and parallel aggregate operations. It is part of the java.util.stream package and provides a powerful way to process collections of data in a functional style.

Table of Contents

  1. What is Stream?
  2. Creating a Stream
  3. Common Operations
  4. Examples of Stream
  5. Real-World Use Case
  6. Conclusion

1. What is Stream?

Stream is an abstraction that allows operations on sequences of elements, such as filtering, mapping, and reducing, without modifying the original data source.

2. Creating a Stream

You can create a Stream in several ways:

  • From a collection:

    List<String> names = List.of("Arjun", "Bhavna", "Chirag");
    Stream<String> streamFromCollection = names.stream();
    
  • From an array:

    String[] nameArray = {"Arjun", "Bhavna", "Chirag"};
    Stream<String> streamFromArray = Arrays.stream(nameArray);
    
  • Using Stream.of(T... values):

    Stream<String> streamOfValues = Stream.of("Arjun", "Bhavna", "Chirag");
    
  • From a file:

    try (Stream<String> streamFromFile = Files.lines(Paths.get("data.txt"))) {
        // Process the stream
    } catch (IOException e) {
        e.printStackTrace();
    }
    
  • Using Stream.generate():

    Stream<Double> randomNumbers = Stream.generate(Math::random).limit(5);
    
  • Using Stream.iterate():

    Stream<Integer> evenNumbers = Stream.iterate(0, n -> n + 2).limit(5);
    

3. Common Operations

Some common operations on Stream include:

  • filter(): Filters elements based on a condition.
  • map(): Transforms elements.
  • collect(): Collects elements into a collection or other data structures.
  • forEach(): Performs an action for each element.
  • reduce(): Performs a reduction on the elements.
  • sorted(): Sorts the elements.
  • distinct(): Removes duplicate elements.
  • limit(): Limits the stream to a certain number of elements.
  • skip(): Skips the first n elements.

4. Examples of Stream

Example 1: Creating and Filtering a Stream

This example demonstrates how to create a Stream from a list of names and filter out elements that do not start with the letter "A".

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

public class FilterExample {
    public static void main(String[] args) {
        List<String> names = List.of("Arjun", "Bhavna", "Amit", "Chirag");

        List<String> filteredNames = names.stream()
                                          .filter(name -> name.startsWith("A"))
                                          .collect(Collectors.toList());

        System.out.println("Filtered Names: " + filteredNames);
    }
}

Output:

Filtered Names: [Arjun, Amit]

Example 2: Mapping and Sorting

This example shows how to map each element of a Stream to its length and then sort the resulting values.

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

public class MapSortExample {
    public static void main(String[] args) {
        List<String> names = List.of("Arjun", "Bhavna", "Chirag");

        List<Integer> lengths = names.stream()
                                     .map(String::length)
                                     .sorted()
                                     .collect(Collectors.toList());

        System.out.println("Sorted Lengths: " + lengths);
    }
}

Output:

Sorted Lengths: [5, 6, 6]

Example 3: Using distinct()

This example demonstrates how to remove duplicate elements from a Stream.

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

public class DistinctExample {
    public static void main(String[] args) {
        List<String> names = List.of("Arjun", "Bhavna", "Arjun", "Chirag", "Bhavna");

        List<String> distinctNames = names.stream()
                                          .distinct()
                                          .collect(Collectors.toList());

        System.out.println("Distinct Names: " + distinctNames);
    }
}

Output:

Distinct Names: [Arjun, Bhavna, Chirag]

Example 4: Using reduce()

This example demonstrates how to use reduce() to concatenate elements.

import java.util.List;
import java.util.Optional;

public class ReduceExample {
    public static void main(String[] args) {
        List<String> names = List.of("Arjun", "Bhavna", "Chirag");

        Optional<String> concatenatedNames = names.stream()
                                                  .reduce((a, b) -> a + ", " + b);

        concatenatedNames.ifPresent(System.out::println);
    }
}

Output:

Arjun, Bhavna, Chirag

Example 5: Using limit() and skip()

This example shows how to limit the stream to the first two elements and skip the first element.

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

public class LimitSkipExample {
    public static void main(String[] args) {
        List<String> names = List.of("Arjun", "Bhavna", "Chirag", "Deepa");

        List<String> limitedNames = names.stream()
                                         .limit(2)
                                         .collect(Collectors.toList());

        List<String> skippedNames = names.stream()
                                         .skip(1)
                                         .collect(Collectors.toList());

        System.out.println("Limited Names: " + limitedNames);
        System.out.println("Skipped Names: " + skippedNames);
    }
}

Output:

Limited Names: [Arjun, Bhavna]
Skipped Names: [Bhavna, Chirag, Deepa]

5. Real-World Use Case: Calculating Total Salary

This example illustrates how to calculate the total salary of employees using Stream.

import java.util.List;

class Employee {
    String name;
    double salary;

    Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }
}

public class TotalSalaryExample {
    public static void main(String[] args) {
        List<Employee> employees = List.of(
            new Employee("Arjun", 50000),
            new Employee("Bhavna", 60000),
            new Employee("Chirag", 55000)
        );

        double totalSalary = employees.stream()
                                      .mapToDouble(emp -> emp.salary)
                                      .sum();

        System.out.println("Total Salary: " + totalSalary);
    }
}

Output:

Total Salary: 165000.0

Conclusion

Stream is used in Java for processing sequences of elements. It provides a range of operations for filtering, transforming, and aggregating data, making it particularly useful in data processing tasks. Using Stream can lead to cleaner and more efficient code, especially in functional programming contexts.

Comments