filter() — keeps all elements that match a predicate, scanning the entire stream. takeWhile() — takes elements while the predicate is true, then stops at the first non-matching element. Think of filter() as a sieve that processes everything, while takeWhile() is like eating from a plate — you eat until you encounter something you don't like, then you stop entirely.
filter():
1List<Integer> result = List.of(1, 2, 3, 4, 5).stream()2 .filter(x -> x < 3)3 .toList();4// [1, 2] — scans all, keeps matching
takeWhile():
1List<Integer> result = List.of(1, 2, 3, 4, 5).stream()2 .takeWhile(x -> x < 3)3 .toList();4// [1, 2] — takes until 3 (which is >= 3)56// Unsorted: behavior depends on encounter order7List<Integer> result = List.of(5, 1, 2, 3, 4).stream()8 .takeWhile(x -> x < 3)9 .toList();10// [5] — stops at 5 because 5 >= 3
How takeWhile works:
When to use takeWhile:
1// Real-world: process orders until a certain date2List<Order> recentOrders = orders.stream()3 .sorted(Comparator.comparing(Order::getDate))4 .takeWhile(o -> o.getDate().isAfter(cutoffDate))5 .collect(Collectors.toList());67// Read sensor data until threshold is exceeded8List<SensorReading> normalReadings = readings.stream()9 .takeWhile(r -> r.getValue() < THRESHOLD)10 .collect(Collectors.toList());
Performance considerations:
.filter(pred).limit(N) instead of takeWhile.Key difference: