Back to Primitive Streams
Q1Question 1 of 2

What are IntStream, LongStream, DoubleStream?

Key Concepts
  • IntStream, LongStream, and DoubleStream operate on primitive values without autoboxing
  • They expose numeric operations not available on Stream<T>: sum, average, min, max, summaryStatistics, range, rangeClosed
  • For 1 million elements, IntStream allocates zero Integer wrapper objects versus 1 million for Stream<Integer>
  • mapToInt/Long/Double converts Stream<T> to a primitive stream; boxed() converts back to Stream<Wrapper>
  • mapToObj converts a primitive stream to Stream<AnyObject>; asLongStream/asDoubleStream widen primitives
  • IntStream.range(0, 10) produces 0-9 exclusive; rangeClosed(1, 10) produces 1-10 inclusive
  • summaryStatistics() computes count, sum, min, max, and average in a single pass

Definition

IntStream, LongStream, and DoubleStream are primitive-specialized streams that avoid autoboxing and provide built-in numeric operations like sum, average, range, and summaryStatistics.
  • No boxing – primitive streams operate on raw int, long, double values without creating wrapper objects (Integer, Long, Double).
  • Numeric operations – sum(), average(), min(), max(), summaryStatistics() are built-in terminal operations.
  • Range factories – IntStream.range(0, 10) (exclusive) and rangeClosed(1, 10) (inclusive) generate sequential values.
  • Conversion – mapToInt converts Stream to IntStream; boxed() converts back; mapToObj converts to Stream.
  • Performance – for 1M elements, IntStream allocates 0 objects vs ~16 MB of Integer objects for Stream.

Stream is like wrapping each coin in a gift box before counting them. IntStream counts bare coins directly: 10x faster for millions of coins, plus a built-in adding machine (sum), average calculator (average), and coin counter (count).

Understanding the Concepts

What are IntStream, LongStream, DoubleStream?

Why does boxing matter?

JAVA
// Stream<Integer>: BOXING - each int becomes an Integer object
int sum1 = java.util.stream.Stream.of(1, 2, 3, 4, 5)
    .reduce(0, Integer::sum);  // unboxing on each add

// IntStream: NO BOXING - pure primitives
int sum2 = java.util.stream.IntStream.of(1, 2, 3, 4, 5).sum();
// Zero Integer objects created

What numeric operations are available?

JAVA
import java.util.stream.IntStream;

IntStream.of(10, 20, 30, 40, 50).sum();           // 150
IntStream.of(10, 20, 30, 40, 50).average();        // OptionalDouble(30.0)
IntStream.of(10, 20, 30, 40, 50).min();             // OptionalInt(10)
IntStream.of(10, 20, 30, 40, 50).max();             // OptionalInt(50)
IntStream.of(10, 20, 30, 40, 50).summaryStatistics();
// IntSummaryStatistics{count=5, sum=150, min=10, average=30.0, max=50}

How do range and rangeClosed work?

JAVA
IntStream.range(0, 5).toArray();          // [0, 1, 2, 3, 4] exclusive end
IntStream.rangeClosed(1, 5).toArray();    // [1, 2, 3, 4, 5] inclusive end

// Index-based iteration
IntStream.range(0, accounts.size()).forEach(i ->
    System.out.println(i + ": " + accounts.get(i).id()));

How do you convert between object and primitive streams?

JAVA
import java.util.stream.*;

// Stream<Trade> -> IntStream
IntStream quantities = trades.stream().mapToInt(Trade::getQuantity);

// IntStream -> Stream<Integer>
Stream<Integer> boxed = IntStream.rangeClosed(1, 5).boxed();

// IntStream -> Stream<String>
Stream<String> labels = IntStream.rangeClosed(1, 5)
    .mapToObj(i -> "TRD-" + String.format("%03d", i));

// IntStream -> LongStream (widening)
LongStream widened = IntStream.of(1, 2, 3).asLongStream();

What about summaryStatistics?

summaryStatistics() computes count, sum, min, max, and average in a single pass.

JAVA
package com.bank.service;

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

public class StatsDemo {
    public static void main(String[] args) {
        int[] dailyTransactions = {150, 200, 175, 190, 210, 185, 195};

        IntSummaryStatistics stats = IntStream.of(dailyTransactions)
            .summaryStatistics();

        System.out.println("Count: " + stats.getCount());     // 7
        System.out.println("Sum: " + stats.getSum());         // 1305
        System.out.println("Min: " + stats.getMin());         // 150
        System.out.println("Max: " + stats.getMax());         // 210
        System.out.println("Avg: " + stats.getAverage());     // 186.43
    }
}

Why not always use IntStream?

You need Stream for APIs that require generic collections, like Collectors.toList() or Collectors.groupingBy. IntStream cannot be used with Collectors directly.

JAVA
// IntStream has no collect(Collectors.toList())
// IntStream.of(1, 2, 3).collect(Collectors.toList()); // COMPILE ERROR

// CORRECT: box first, then collect
List<Integer> list = IntStream.of(1, 2, 3).boxed().collect(Collectors.toList());

// Or use toList() on boxed stream
List<Integer> list = IntStream.of(1, 2, 3).boxed().toList();

What about money calculations?

For monetary calculations, use BigDecimal with Stream and reduce, not DoubleStream. Floating-point imprecision is unacceptable for money.

JAVA
// WRONG: DoubleStream for money
double total = accounts.stream().mapToDouble(a -> a.getBalance()).sum();
// Floating-point imprecision!

// CORRECT: BigDecimal with reduce
BigDecimal total = accounts.stream()
    .map(Account::balance)
    .reduce(BigDecimal.ZERO, BigDecimal::add);

What should a senior engineer know?

  • summaryStatistics() computes count, sum, min, max, and average in a single pass.
  • For monetary calculations, use BigDecimal with Stream and reduce, not DoubleStream.
  • IntStream.range is useful for index-based iteration: IntStream.range(0, list.size()).forEach(i -> ...).
  • Does DoubleStream have range? No. Use IntStream.range and mapToDouble for sequential doubles.
  • IntStream.average() returns OptionalDouble, not double, because the stream might be empty.

Visual Overview

DIAGRAM
  Conversion Bridge:

  Stream<Trade>  ──mapToInt──▶  IntStream
                                  │
                   ┌──────────────┼──────────────┐
                   ▼              ▼              ▼
               boxed()       mapToObj()     asLongStream()
                   │              │              │
                   ▼              ▼              ▼
           Stream<Integer>  Stream<String>  LongStream

Key Takeaway

IntStream, LongStream, and DoubleStream are primitive-specialized streams that avoid autoboxing and provide built-in numeric operations. Stream creates a wrapper object for every element; IntStream operates on raw primitives with zero allocation. The built-in operations (sum, average, min, max, summaryStatistics, range, rangeClosed) make numeric processing concise and efficient.

The conversion methods form a complete bridge: mapToInt/Long/Double converts Stream to primitive stream. boxed() converts back. mapToObj converts to Stream. asLongStream and asDoubleStream widen primitives. In performance-critical banking code, always prefer IntStream over Stream for large numeric datasets.

Remember one sentence: primitive streams avoid boxing overhead and provide built-in sum, average, range, and summaryStatistics that Stream lacks.

---

Share
Use ← → arrow keys to navigate