Java Stream API Cheatsheet
Table of Contents
- Stream Creation
- Intermediate Operations
- Terminal Operations
- Collectors
- Primitive Streams
- Common Patterns
- Performance Tips
Stream Creation
From Collections
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
Stream<String> parallelStream = list.parallelStream();
From Arrays
String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
Stream<String> streamPart = Arrays.stream(array, 1, 3); // from index 1 to 2
Static Methods
Stream<String> empty = Stream.empty();
Stream<String> single = Stream.of("a");
Stream<String> multiple = Stream.of("a", "b", "c");
Stream<Integer> infinite = Stream.generate(() -> 1);
Stream<Integer> sequence = Stream.iterate(0, n -> n + 2); // 0, 2, 4, 6...
Stream<Integer> limited = Stream.iterate(0, n -> n < 10, n -> n + 1); // Java 9+
From Files and I/O
Stream<String> lines = Files.lines(Paths.get("file.txt"));
Stream<Path> paths = Files.walk(Paths.get("directory"));
From Random Numbers
Random random = new Random();
Stream<Integer> randomInts = random.ints().boxed();
IntStream randomIntStream = random.ints(10); // 10 random integers
Intermediate Operations
Filtering
stream.filter(x -> x.length() > 2)
stream.filter(Objects::nonNull)
stream.filter(String::isEmpty)
Mapping
stream.map(String::toUpperCase)
stream.map(s -> s.length())
stream.mapToInt(String::length) // Returns IntStream
stream.mapToLong(Long::parseLong)
stream.mapToDouble(Double::parseDouble)
Flat Mapping
// Flatten nested collections
stream.flatMap(Collection::stream)
stream.flatMapToInt(s -> s.chars()) // String to IntStream of characters
Sorting
stream.sorted() // Natural ordering
stream.sorted(Comparator.reverseOrder())
stream.sorted(Comparator.comparing(String::length))
stream.sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge))
Limiting and Skipping
stream.limit(5) // First 5 elements
stream.skip(3) // Skip first 3 elements
stream.takeWhile(x -> x.length() < 5) // Java 9+
stream.dropWhile(x -> x.length() < 5) // Java 9+
Distinct and Peek
stream.distinct() // Remove duplicates
stream.peek(System.out::println) // Debug/side effects
Terminal Operations
Collection Operations
List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());
String joined = stream.collect(Collectors.joining(", "));
Finding Elements
Optional<String> first = stream.findFirst();
Optional<String> any = stream.findAny();
boolean anyMatch = stream.anyMatch(s -> s.startsWith("a"));
boolean allMatch = stream.allMatch(s -> s.length() > 0);
boolean noneMatch = stream.noneMatch(String::isEmpty);
Reduction
Optional<String> reduced = stream.reduce((a, b) -> a + b);
String reduced = stream.reduce("", (a, b) -> a + b);
int sum = stream.reduce(0, Integer::sum);
Counting and Statistics
long count = stream.count();
OptionalInt max = intStream.max();
OptionalInt min = intStream.min();
For Each
stream.forEach(System.out::println);
stream.forEachOrdered(System.out::println); // Maintains order in parallel streams
Collectors
Basic Collectors
// To Collections
.collect(Collectors.toList())
.collect(Collectors.toSet())
.collect(Collectors.toCollection(TreeSet::new))
// To Map
.collect(Collectors.toMap(keyMapper, valueMapper))
.collect(Collectors.toMap(Person::getId, Function.identity()))
// Joining
.collect(Collectors.joining())
.collect(Collectors.joining(", "))
.collect(Collectors.joining(", ", "[", "]"))
Grouping and Partitioning
// Group by
Map<Integer, List<String>> byLength =
stream.collect(Collectors.groupingBy(String::length));
Map<Integer, Set<String>> byLengthSet =
stream.collect(Collectors.groupingBy(String::length, Collectors.toSet()));
// Partition (boolean grouping)
Map<Boolean, List<String>> partition =
stream.collect(Collectors.partitioningBy(s -> s.length() > 3));
Statistical Collectors
// Counting
Map<String, Long> counts =
stream.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// Statistics
IntSummaryStatistics stats =
stream.collect(Collectors.summarizingInt(String::length));
// Min/Max
Optional<String> longest =
stream.collect(Collectors.maxBy(Comparator.comparing(String::length)));
Advanced Collectors
// Downstream collectors
Map<Integer, String> lengthToJoined = stream.collect(
Collectors.groupingBy(String::length, Collectors.joining(", ")));
// Mapping collector
Set<Integer> lengths = stream.collect(
Collectors.mapping(String::length, Collectors.toSet()));
// Filtering collector (Java 9+)
List<String> longStrings = stream.collect(
Collectors.filtering(s -> s.length() > 3, Collectors.toList()));
Primitive Streams
IntStream
IntStream.range(1, 5) // 1, 2, 3, 4
IntStream.rangeClosed(1, 5) // 1, 2, 3, 4, 5
IntStream.of(1, 2, 3, 4, 5)
// Statistics
OptionalInt max = intStream.max();
OptionalInt min = intStream.min();
int sum = intStream.sum();
OptionalDouble average = intStream.average();
IntSummaryStatistics stats = intStream.summaryStatistics();
LongStream and DoubleStream
LongStream.range(1L, 1000000L)
DoubleStream.of(1.0, 2.0, 3.0)
// Convert between streams
intStream.asLongStream()
intStream.asDoubleStream()
intStream.boxed() // IntStream to Stream<Integer>
Common Patterns
Find Maximum/Minimum
// Find person with max age
Optional<Person> oldest = people.stream()
.max(Comparator.comparing(Person::getAge));
// Find longest string
Optional<String> longest = strings.stream()
.max(Comparator.comparing(String::length));
Group and Count
// Count occurrences
Map<String, Long> wordCounts = words.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// Group by property and count
Map<String, Long> countByCity = people.stream()
.collect(Collectors.groupingBy(Person::getCity, Collectors.counting()));
Nested Grouping
// Group by department, then by salary range
Map<String, Map<String, List<Employee>>> grouped = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.groupingBy(emp -> emp.getSalary() > 50000 ? "High" : "Low")));
Custom Collectors
// Create a custom collector for comma-separated values
Collector<String, ?, String> customJoining = Collector.of(
StringBuilder::new, // supplier
(sb, s) -> sb.append(s).append(", "), // accumulator
StringBuilder::append, // combiner
sb -> sb.toString() // finisher
);