Mastering IntStream in Java 8

A cup of JAVA coffee with NeeSri
6 min readJan 25, 2024

--

In Java 8 and later versions, the Stream API is designed to work with objects, not primitive types directly. However, the Stream API provides special primitive-type streams to handle primitive values efficiently. These streams are named as follows:

  1. IntStream: A stream of primitive ints.
  2. LongStream: A stream of primitive longs.
  3. DoubleStream: A stream of primitive doubles.

Many developers were curious about how Java will handle the primitive data type with streams.
So in this article we will discuss about how we can use Streams API with primitive and what are the current limitation and how to overcome them.

Current Design
If you see Stream Interface that provides lot of great features to process elements in a collection, it extends from BaseStream interface.
BaseStream Interface is also extended by IntStream, DoubleStream and LongStream Interface.

You can convert a regular Stream to a primitive-type stream using methods like mapToInt, mapToLong, or mapToDouble. Conversely, you can convert a primitive-type stream to a regular Stream using methods like boxed().

Here’s an example of using IntStream

import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.stream.IntStream;

public class PrimitiveStreamExample {

public static void main(String[] args) {
int[] intArray = {1, 2, 3, 4, 5};

// Using IntStream
IntStream intStream = Arrays.stream(intArray);

// Example operations on IntStream
int sum = intStream.sum();
System.out.println("Sum: " + sum);

IntSummaryStatistics stats = Arrays.stream(intArray).summaryStatistics();
System.out.println("Statistics: " + stats);

// Convert IntStream to Stream<Integer>
IntStream intStream2 = Arrays.stream(intArray);
intStream2.boxed().forEach(System.out::println);
}
}

In this example, we use IntStream to perform operations on an array of integers. You can similarly use LongStream and DoubleStream for long and double values, respectively.

  1. Creating a primitive stream from a collection:
List<Integer> numbersList = Arrays.asList(1, 2, 3, 4, 5);

IntStream intStream = numbersList.stream().mapToInt(Integer::intValue);

2. Creating a primitive stream using range and rangeClosed methods:

IntStream intRange = IntStream.range(1, 5);          // 1, 2, 3, 4
IntStream intRangeClosed = IntStream.rangeClosed(1, 5); // 1, 2, 3, 4, 5

3. Performing operations on a primitive stream:

IntStream intStream = IntStream.of(1, 2, 3, 4, 5);

int sum = intStream.sum();
OptionalInt max = intStream.max();
OptionalInt min = intStream.min();

4. Converting a primitive stream back to a collection:

IntStream intStream = IntStream.of(1, 2, 3, 4, 5);

List<Integer> resultList = intStream.boxed().collect(Collectors.toList());

Remember that using primitive-type streams can improve performance in certain scenarios, as they avoid the overhead of autoboxing and unboxing. However, the choice between regular and primitive streams depends on your specific use case and requirements.

Here’s an example showcasing various methods available in Java 8 for working with IntStream:

import java.util.IntSummaryStatistics;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.stream.IntStream;

public class IntStreamExample {

public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// 1. forEach
System.out.println("1. forEach:");
IntStream.of(numbers).forEach(System.out::println);

// 2. sum
System.out.println("\n2. sum:");
int sum = IntStream.of(numbers).sum();
System.out.println("Sum: " + sum);

// 3. average
System.out.println("\n3. average:");
OptionalDouble average = IntStream.of(numbers).average();
System.out.println("Average: " + average.orElse(0.0));

// 4. min
System.out.println("\n4. min:");
OptionalInt min = IntStream.of(numbers).min();
System.out.println("Min: " + min.orElse(0));

// 5. max
System.out.println("\n5. max:");
OptionalInt max = IntStream.of(numbers).max();
System.out.println("Max: " + max.orElse(0));

// 6. count
System.out.println("\n6. count:");
long count = IntStream.of(numbers).count();
System.out.println("Count: " + count);

// 7. summaryStatistics
System.out.println("\n7. summaryStatistics:");
IntSummaryStatistics stats = IntStream.of(numbers)
.summaryStatistics();
System.out.println("Stats: " + stats);

// 8. filter and collect
System.out.println("\n8. filter and collect:");
int[] evenNumbers = IntStream.of(numbers)
.filter(n -> n % 2 == 0)
.toArray();
System.out.print("Even Numbers: ");
IntStream.of(evenNumbers).forEach(System.out::print);

// 9. map and sum
System.out.println("\n\n9. map and sum:");
int squaredSum = IntStream.of(numbers)
.map(n -> n * n)
.sum();
System.out.println("Sum of Squares: " + squaredSum);
}
}

Explanation:

  1. forEach: Iterates over each element in the stream and applies the given action.
  2. sum: Calculates the sum of elements in the stream.
  3. average: Calculates the average of elements in the stream.
  4. min: Finds the minimum element in the stream.
  5. max: Finds the maximum element in the stream.
  6. count: Counts the number of elements in the stream.
  7. summaryStatistics: Collects statistics, including count, sum, min, average, and max.
  8. filter and collect: Filters elements based on a condition (even numbers in this case) and collects them into an array.
  9. map and sum: Maps each element to its square and calculates the sum of the squared values.

These examples demonstrate various methods available in IntStream in Java 8 for processing and manipulating primitive integers.

— -— IntStream Interview Questions — — ——

  1. What is IntStream in Java?
  • IntStream is a specialized stream for handling primitive integers (int). It provides a sequence of primitive int values and supports various operations such as filtering, mapping, reduction, and iteration.

2. How do you create an IntStream in Java?

  • You can create an IntStream in Java using factory methods like IntStream.range(int startInclusive, int endExclusive) or IntStream.rangeClosed(int startInclusive, int endInclusive) to create a stream of integers within a specified range, or by converting other data structures like arrays or collections using Arrays.stream(int[] array) or Collection.stream().mapToInt().

3. What are the terminal operations you can perform on an IntStream

  • Common terminal operations include forEach, sum, average, min, max, count, and reduce. These operations consume the elements of the stream and produce a result or a side effect.

4. How do you perform mapping operations on an IntStream?

  • You can perform mapping operations on an IntStream using methods like mapToInt, mapToLong, and mapToDouble. These methods transform each element of the stream into another type or value.

5. Explain the usage of filter in IntStream.

  • The filter method in IntStream is used to eliminate elements from the stream based on a specified condition. It takes a predicate as an argument and retains only those elements that satisfy the predicate.

Question: How can you filter elements in an IntStream?

You can use the filter method, which takes a predicate. For example:

IntStream.range(1, 10)
.filter(n -> n % 2 == 0)
.forEach(System.out::println);

6. How do you perform reduction operations on an IntStream?

  • Reduction operations in IntStream are performed using methods like reduce, sum, average, min, and max. These operations aggregate the elements of the stream into a single result by applying a binary operator to each element.

Question: How would you find the maximum element in an IntStream?

  • Answer: You can use the max() method. For example:
int max = IntStream.of
(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5)
.max().orElse(0);

7. What is the difference between range and rangeClosed methods in IntStream?

  • IntStream.range(int startInclusive, int endExclusive) creates a stream of integers starting from startInclusive up to, but not including, endExclusive.
  • In contrast, IntStream.rangeClosed(int startInclusive, int endInclusive) creates a stream of integers starting from startInclusive up to and including endInclusive.

These questions cover the basics of IntStream and its usage in Java, which are often discussed in interviews to assess a candidate's understanding of stream processing and functional programming concepts.

8. Question: Given an array of integers, write a Java program to find the sum of the squares of even numbers using IntStream ?

Example:

For the array [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], the program should calculate the sum of the squares of even numbers (2^2 + 4^2 + 6^2 + 8^2 + 10^2) and print the result.

Solution:

import java.util.Arrays;
import java.util.stream.IntStream;

public class SumOfSquaresOfEvenNumbers {

public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int sumOfSquaresOfEvens = calculateSumOfSquaresOfEvens(array);

System.out.println("Sum of squares of even numbers: "
+ sumOfSquaresOfEvens);
}

public static int calculateSumOfSquaresOfEvens(int[] array) {
return Arrays.stream(array)
.filter(n -> n % 2 == 0) // Filter even numbers
.map(n -> n * n) // Square each even number
.sum(); // Calculate the sum
}
}

Explanation:

  1. Arrays.stream(array): Converts the array to an IntStream.
  2. .filter(n -> n % 2 == 0): Filters out only the even numbers.
  3. .map(n -> n * n): Squares each even number.
  4. .sum(): Calculates the sum of the squared even numbers.

This question tests the candidate’s understanding of how to use IntStream along with various stream operations to perform a specific task.

--

--

No responses yet