peek is an intermediate Stream operation whose Consumer observes elements without changing their values. Treat it as a debugging aid, not as a dependable way to populate external state: execution can be skipped when the pipeline optimizes away elements. section 9.2
A fragile collection side effect
List<String> trimmed = new ArrayList<>(); List<String> trimmedLong = strings.stream() .map(String::trim) .peek(trimmed::add) .filter(s -> s.length() > 10) .limit(5) .toList(); Here, limit(5) can stop traversal before every trimmed element reaches peek, so trimmed may be incomplete. Build trimmed in a separate stream instead. section 9.2
Avoid treating peek as ordinary pipeline logic:
- Use map, filter, or a collector for transformations and results rather than mutating external collections from an intermediate operation. section 9.2
- Expect ordering and thread-safety problems when side effects run concurrently through parallelStream(). section 9.2
List<String> trimmed = strings.stream() .map(String::trim).toList(); List<String> trimmedLong = trimmed.stream() .filter(s -> s.length() > 10).limit(5).toList();
Separate the trimmed result from the filtered-and-limited result so each stream performs a complete, explicit operation. section 9.2


