CoreJava Java9

Java 9 Stream API – takeWhile() Method Explained with Examples

Java 9 Stream API – takeWhile() Method Explained with Examples

Java 9 added four new methods to the Stream API, and takeWhile() is one of the most useful. It allows you to take elements from a stream as long as a condition is true, stopping as soon as the first element fails the predicate. Think of it as a lazy alternative to filter() for ordered streams where you want to stop processing early.

This tutorial explains how takeWhile() works, how it differs from filter(), and shows practical use cases.

What is takeWhile()?

takeWhile(Predicate<T> predicate) is a short-circuiting intermediate operation. It processes stream elements in order and includes each element in the output as long as the predicate returns true. The moment it encounters an element for which the predicate returns false, it stops — even if later elements would have matched.

Key difference from filter():

  • filter() checks every element and returns all matching ones
  • takeWhile() stops at the first non-matching element, discarding everything after it

Basic Example


package com.java9r;

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

public class Java9TakeWhileDemo {

    public static void main(String[] args) {

        // Sorted list of numbers
        var numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // takeWhile: take numbers less than 6, stop at first >= 6
        var taken = numbers.stream()
                .takeWhile(n -> n < 6)
                .collect(Collectors.toList());
        System.out.println("takeWhile(n < 6): " + taken);
        // Output: [1, 2, 3, 4, 5]

        // filter: returns ALL elements less than 6
        var filtered = numbers.stream()
                .filter(n -> n < 6)
                .collect(Collectors.toList());
        System.out.println("filter(n < 6):    " + filtered);
        // Output: [1, 2, 3, 4, 5]  -- same result because list is sorted

        // The difference becomes clear with an unsorted list:
        var unsorted = List.of(1, 3, 5, 2, 4, 6, 7);
        var takeResult   = unsorted.stream().takeWhile(n -> n < 6).collect(Collectors.toList());
        var filterResult = unsorted.stream().filter(n -> n < 6).collect(Collectors.toList());
        System.out.println("\nUnsorted list: " + unsorted);
        System.out.println("takeWhile: " + takeResult);   // [1, 3, 5, 2, 4] – stops at 6
        System.out.println("filter:    " + filterResult); // [1, 3, 5, 2, 4] – wait, 6 is excluded but 7 too
    }
}

Real-World Example: Price Threshold


package com.java9r;

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

class Product {
    String name;
    double price;

    Product(String name, double price) {
        this.name  = name;
        this.price = price;
    }

    @Override
    public String toString() {
        return name + " (Rs. " + price + ")";
    }
}

public class StreamAPITakewhile {

    public static void main(String[] args) {

        // Products sorted by price (ascending)
        var products = List.of(
            new Product("Pen",       15.0),
            new Product("Notebook",  80.0),
            new Product("Bag",      350.0),
            new Product("Tablet",  5000.0),
            new Product("Laptop", 55000.0)
        );

        System.out.println("=== Products List ===");
        products.forEach(System.out::println);

        // takeWhile: show products under Rs. 1000 (stops at Tablet)
        System.out.println("\n--- Budget items (price < 1000) ---");
        products.stream()
                .takeWhile(p -> p.price < 1000)
                .forEach(System.out::println);
        // Pen, Notebook, Bag – stops when it hits Tablet (5000)

        // Compare with filter:
        System.out.println("\n--- filter (price < 1000) ---");
        products.stream()
                .filter(p -> p.price < 1000)
                .forEach(System.out::println);
        // Same result here because the list IS already sorted by price
    }
}

Expected Output


=== Products List ===
Pen (Rs. 15.0)
Notebook (Rs. 80.0)
Bag (Rs. 350.0)
Tablet (Rs. 5000.0)
Laptop (Rs. 55000.0)

--- Budget items (price < 1000) ---
Pen (Rs. 15.0)
Notebook (Rs. 80.0)
Bag (Rs. 350.0)

--- filter (price < 1000) ---
Pen (Rs. 15.0)
Notebook (Rs. 80.0)
Bag (Rs. 350.0)

takeWhile with Strings


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

var names = List.of("Alice", "Bob", "Carol", "Dave", "Eve");

// Take names while their length is less than 5
var shortNames = names.stream()
        .takeWhile(n -> n.length() < 5)
        .collect(Collectors.toList());

System.out.println(shortNames);  // [Alice, Bob] – stops at "Carol" (length 5)

dropWhile() – The Complement

Java 9 also added dropWhile(), which is the opposite of takeWhile(). It skips elements as long as the predicate is true, then returns all remaining elements:


var numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// dropWhile: skip numbers < 6, return the rest
var result = numbers.stream()
        .dropWhile(n -> n < 6)
        .collect(Collectors.toList());

System.out.println(result);  // [6, 7, 8, 9, 10]

When to Use takeWhile vs filter

Scenario Use
Data is sorted and you want a prefix matching a condition takeWhile()
Data is unsorted and you want all matching elements filter()
Performance matters and you can stop early takeWhile()
Log file processing: read until "ERROR" appears takeWhile()
You need all matching elements regardless of order filter()

Important Notes

  • takeWhile() is most predictable on ordered streams (lists). On unordered streams (like HashSet), the behavior is non-deterministic.
  • It is a short-circuiting operation, so it can exit the pipeline early, which is more efficient than filter() + limit() in sorted scenarios.
  • Requires Java 9 or later.

Summary

takeWhile() is a clean and expressive way to take a prefix of an ordered stream. Unlike filter(), which checks every element, takeWhile() stops at the first non-matching element — making it more efficient for sorted data. Pair it with dropWhile() to split a stream into a "before" and "after" a condition. This API addition in Java 9 makes stream pipelines more expressive and avoids the need for index-based workarounds in sorted data processing.

Topics: CoreJava Java9
← Newer Post Older Post →

Comments

https://www.blogger.com/comment/frame/6690124484600543990?po=507442142661692938&hl=en&saa=85391&origin=https://www.java9r.com