takeWhile and dropWhile

Streams · lesson 20 of 42 · 3 min read

Cut a stream at the first element that fails the test, instead of testing every element.

Open this lesson in the learning hub

Key points

  • takeWhile(p) keeps elements until the first one that fails, then stops reading the source entirely.
  • dropWhile(p) throws away that same leading run and keeps everything after it, failures included.
  • This is the difference from filter: filter examines every element, these two care only about the prefix.
  • Put the two results back together and you get the original list, in order, every time.
  • They shine on sorted or time ordered data, and on infinite sources where they replace limit with a real condition.
  • On an unordered parallel stream the prefix is not well defined, so the result can surprise you.

Example

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        List<Integer> nums = List.of(1, 3, 5, 4, 7, 2);

        System.out.println("takeWhile < 5 : " + nums.stream().takeWhile(n -> n < 5).toList());
        System.out.println("dropWhile < 5 : " + nums.stream().dropWhile(n -> n < 5).toList());
        System.out.println("filter    < 5 : " + nums.stream().filter(n -> n < 5).toList());

        // takeWhile plus dropWhile always rebuilds the original list.
        List<Integer> rejoined = new ArrayList<>(nums.stream().takeWhile(n -> n < 5).toList());
        rejoined.addAll(nums.stream().dropWhile(n -> n < 5).toList());
        System.out.println("rejoined      : " + rejoined + "  same? " + rejoined.equals(nums));

        // Sorted data is where takeWhile earns its keep: it stops instead of scanning on.
        List<Integer> sorted = nums.stream().sorted().toList();
        System.out.println("sorted        : " + sorted);
        System.out.println("sorted take   : " + sorted.stream().takeWhile(n -> n < 5).toList());

        // It also bounds an infinite source without limit().
        System.out.println("powers < 100  : " + Stream.iterate(1, i -> i * 3).takeWhile(i -> i < 100).toList());
    }
}

takeWhile cuts at the first failure; filter keeps looking to the end.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.