Overview
Streams in Java provide a powerful way to process sequences of elements. They can be created from various data sources including collections, arrays, I/O channels, and generator functions.
1. Streams from Collections
Basic Collection Streams
import java.util.*;
import java.util.stream.*;
public class CollectionStreams {
public static void main(String[] args) {
// List to Stream
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Diana");
Stream<String> nameStream = names.stream();
System.out.println("List stream count: " + nameStream.count());
// Set to Stream
Set<Integer> numbers = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
Stream<Integer> numberStream = numbers.stream();
System.out.println("Set stream count: " + numberStream.count());
// Map to Stream
Map<String, Integer> ageMap = new HashMap<>();
ageMap.put("Alice", 25);
ageMap.put("Bob", 30);
ageMap.put("Charlie", 35);
// Stream of keys
Stream<String> keyStream = ageMap.keySet().stream();
System.out.println("Keys: " + keyStream.collect(Collectors.toList()));
// Stream of values
Stream<Integer> valueStream = ageMap.values().stream();
System.out.println("Values: " + valueStream.collect(Collectors.toList()));
// Stream of entries
Stream<Map.Entry<String, Integer>> entryStream = ageMap.entrySet().stream();
entryStream.forEach(entry ->
System.out.println(entry.getKey() + ": " + entry.getValue()));
}
}
Parallel Streams from Collections
import java.util.*;
import java.util.stream.*;
public class ParallelStreams {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Sequential stream
long startTime = System.currentTimeMillis();
List<Integer> squares = numbers.stream()
.map(n -> {
try { Thread.sleep(100); } catch (Exception e) {}
return n * n;
})
.collect(Collectors.toList());
long sequentialTime = System.currentTimeMillis() - startTime;
// Parallel stream
startTime = System.currentTimeMillis();
List<Integer> squaresParallel = numbers.parallelStream()
.map(n -> {
try { Thread.sleep(100); } catch (Exception e) {}
return n * n;
})
.collect(Collectors.toList());
long parallelTime = System.currentTimeMillis() - startTime;
System.out.println("Sequential time: " + sequentialTime + "ms");
System.out.println("Parallel time: " + parallelTime + "ms");
System.out.println("Results equal: " + squares.equals(squaresParallel));
}
}
2. Streams from Arrays
Basic Array Streams
import java.util.*;
import java.util.stream.*;
public class ArrayStreams {
public static void main(String[] args) {
// Primitive array streams
int[] intArray = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(intArray);
System.out.println("Int stream sum: " + intStream.sum());
double[] doubleArray = {1.1, 2.2, 3.3, 4.4, 5.5};
DoubleStream doubleStream = Arrays.stream(doubleArray);
System.out.println("Double stream average: " + doubleStream.average().orElse(0));
long[] longArray = {100L, 200L, 300L};
LongStream longStream = Arrays.stream(longArray);
System.out.println("Long stream count: " + longStream.count());
// Object array streams
String[] stringArray = {"Apple", "Banana", "Cherry"};
Stream<String> stringStream = Arrays.stream(stringArray);
System.out.println("String stream: " + stringStream.collect(Collectors.toList()));
// Stream with range
String[] partialArray = {"A", "B", "C", "D", "E"};
Stream<String> partialStream = Arrays.stream(partialArray, 1, 4); // B, C, D
System.out.println("Partial stream: " + partialStream.collect(Collectors.toList()));
}
}
Multi-dimensional Array Streams
import java.util.*;
import java.util.stream.*;
public class MultiDimensionalArrayStreams {
public static void main(String[] args) {
// 2D array
Integer[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Flatten 2D array to 1D stream
Stream<Integer> flatStream = Arrays.stream(matrix)
.flatMap(Arrays::stream);
System.out.println("Flattened matrix: " + flatStream.collect(Collectors.toList()));
// Process rows
Stream<Integer[]> rowStream = Arrays.stream(matrix);
rowStream.forEach(row ->
System.out.println("Row: " + Arrays.toString(row)));
// 3D array example
Integer[][][] cube = {
{{1, 2}, {3, 4}},
{{5, 6}, {7, 8}}
};
// Flatten 3D array
Stream<Integer> cubeStream = Arrays.stream(cube)
.flatMap(Arrays::stream)
.flatMap(Arrays::stream);
System.out.println("Flattened cube: " + cubeStream.collect(Collectors.toList()));
}
}
3. Stream Factory Methods
Stream.of()
import java.util.*;
import java.util.stream.*;
public class StreamOfMethods {
public static void main(String[] args) {
// Stream.of() with individual elements
Stream<String> singleElementStream = Stream.of("Hello");
System.out.println("Single element: " + singleElementStream.collect(Collectors.toList()));
Stream<String> multipleElementsStream = Stream.of("Apple", "Banana", "Cherry");
System.out.println("Multiple elements: " + multipleElementsStream.collect(Collectors.toList()));
// Stream.of() with array
Stream<Integer> arrayStream = Stream.of(1, 2, 3, 4, 5);
System.out.println("Array elements: " + arrayStream.collect(Collectors.toList()));
// Stream of different types
Stream<Object> mixedStream = Stream.of("String", 42, 3.14, true);
mixedStream.forEach(obj ->
System.out.println(obj + " (" + obj.getClass().getSimpleName() + ")"));
// Empty stream
Stream<String> emptyStream = Stream.of();
System.out.println("Empty stream count: " + emptyStream.count());
// Null handling
Stream<String> withNull = Stream.of("A", null, "C");
withNull.forEach(element ->
System.out.println("Element: " + element));
}
}
Stream.builder()
import java.util.*;
import java.util.stream.*;
public class StreamBuilderExample {
public static void main(String[] args) {
// Using Stream.builder()
Stream.Builder<String> builder = Stream.builder();
builder.add("First")
.add("Second")
.add("Third")
.add("Fourth");
Stream<String> builtStream = builder.build();
System.out.println("Built stream: " + builtStream.collect(Collectors.toList()));
// Conditional building
Stream.Builder<Integer> conditionalBuilder = Stream.builder();
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) { // Only add even numbers
conditionalBuilder.add(i);
}
}
Stream<Integer> evenStream = conditionalBuilder.build();
System.out.println("Even numbers: " + evenStream.collect(Collectors.toList()));
// Complex object building
Stream.Builder<Person> personBuilder = Stream.builder();
personBuilder.add(new Person("Alice", 25))
.add(new Person("Bob", 30))
.add(new Person("Charlie", 35));
Stream<Person> personStream = personBuilder.build();
personStream.forEach(p -> System.out.println(p.name + " - " + p.age));
}
static class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
}
4. Specialized Streams
IntStream, LongStream, DoubleStream
import java.util.*;
import java.util.stream.*;
public class SpecializedStreams {
public static void main(String[] args) {
// IntStream examples
System.out.println("=== IntStream ===");
IntStream.range(1, 6).forEach(System.out::println); // 1,2,3,4,5
IntStream.rangeClosed(1, 5).forEach(System.out::println); // 1,2,3,4,5
int sum = IntStream.of(1, 2, 3, 4, 5).sum();
System.out.println("Sum: " + sum);
OptionalDouble average = IntStream.range(1, 11).average();
System.out.println("Average: " + average.orElse(0));
// LongStream examples
System.out.println("\n=== LongStream ===");
LongStream.range(100L, 105L).forEach(System.out::println);
long product = LongStream.rangeClosed(1L, 5L)
.reduce(1, (a, b) -> a * b);
System.out.println("Product: " + product);
// DoubleStream examples
System.out.println("\n=== DoubleStream ===");
DoubleStream.of(1.1, 2.2, 3.3, 4.4, 5.5)
.forEach(d -> System.out.printf("%.1f ", d));
System.out.println();
double[] doubles = DoubleStream.generate(Math::random)
.limit(5)
.toArray();
System.out.println("Random doubles: " + Arrays.toString(doubles));
// Converting between stream types
System.out.println("\n=== Conversions ===");
IntStream intStream = IntStream.range(1, 6);
Stream<Integer> boxedStream = intStream.boxed();
System.out.println("Boxed stream: " + boxedStream.collect(Collectors.toList()));
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
IntStream unboxedStream = integerStream.mapToInt(Integer::intValue);
System.out.println("Sum of unboxed: " + unboxedStream.sum());
}
}
5. Infinite Streams
Stream.generate()
import java.util.*;
import java.util.stream.*;
import java.util.concurrent.atomic.*;
public class GenerateStreams {
public static void main(String[] args) {
// Generate random numbers
System.out.println("=== Random Numbers ===");
Stream<Double> randomStream = Stream.generate(Math::random)
.limit(5);
randomStream.forEach(System.out::println);
// Generate constant values
System.out.println("\n=== Constant Values ===");
Stream<String> constantStream = Stream.generate(() -> "Hello")
.limit(3);
constantStream.forEach(System.out::println);
// Generate with state (using AtomicInteger)
System.out.println("\n=== Stateful Generation ===");
AtomicInteger counter = new AtomicInteger(1);
Stream<Integer> statefulStream = Stream.generate(() -> counter.getAndIncrement())
.limit(5);
statefulStream.forEach(System.out::println);
// Generate Fibonacci sequence
System.out.println("\n=== Fibonacci Sequence ===");
long[] fib = {0, 1};
Stream<Long> fibonacciStream = Stream.generate(() -> {
long next = fib[0] + fib[1];
long result = fib[0];
fib[0] = fib[1];
fib[1] = next;
return result;
}).limit(10);
fibonacciStream.forEach(n -> System.out.print(n + " "));
System.out.println();
// Generate UUIDs
System.out.println("\n=== UUIDs ===");
Stream<String> uuidStream = Stream.generate(() -> UUID.randomUUID().toString())
.limit(3);
uuidStream.forEach(System.out::println);
}
}
Stream.iterate()
import java.util.*;
import java.util.stream.*;
public class IterateStreams {
public static void main(String[] args) {
// Basic iterate - arithmetic sequence
System.out.println("=== Arithmetic Sequence ===");
Stream<Integer> arithmetic = Stream.iterate(0, n -> n + 2)
.limit(5);
arithmetic.forEach(n -> System.out.print(n + " ")); // 0, 2, 4, 6, 8
System.out.println();
// Geometric sequence
System.out.println("\n=== Geometric Sequence ===");
Stream<Integer> geometric = Stream.iterate(1, n -> n * 2)
.limit(6);
geometric.forEach(n -> System.out.print(n + " ")); // 1, 2, 4, 8, 16, 32
System.out.println();
// Fibonacci with iterate
System.out.println("\n=== Fibonacci with Iterate ===");
Stream.iterate(new long[]{0, 1}, fib -> new long[]{fib[1], fib[0] + fib[1]})
.limit(10)
.map(fib -> fib[0])
.forEach(n -> System.out.print(n + " "));
System.out.println();
// Conditional iteration with predicate (Java 9+)
System.out.println("\n=== Conditional Iteration ===");
Stream<Integer> limited = Stream.iterate(1, n -> n <= 32, n -> n * 2);
limited.forEach(n -> System.out.print(n + " ")); // 1, 2, 4, 8, 16, 32
System.out.println();
// String sequence
System.out.println("\n=== String Sequence ===");
Stream.iterate("A", s -> s + s.charAt(0))
.limit(5)
.forEach(System.out::println);
}
}
6. Streams from I/O Operations
Files.lines()
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;
public class FileStreams {
public static void main(String[] args) {
try {
// Create a sample file
Path tempFile = Files.createTempFile("sample", ".txt");
List<String> lines = Arrays.asList(
"Line 1: Hello World",
"Line 2: Java Streams",
"Line 3: File Processing",
"Line 4: Lambda Expressions",
"Line 5: Functional Programming"
);
Files.write(tempFile, lines);
// Read file as stream
System.out.println("=== Reading File as Stream ===");
try (Stream<String> fileStream = Files.lines(tempFile)) {
fileStream.forEach(System.out::println);
}
// Process file content
System.out.println("\n=== Processing File Content ===");
try (Stream<String> processedStream = Files.lines(tempFile)) {
long lineCount = processedStream
.filter(line -> line.contains("Java"))
.count();
System.out.println("Lines containing 'Java': " + lineCount);
}
// Read and transform
System.out.println("\n=== Transforming File Content ===");
try (Stream<String> transformStream = Files.lines(tempFile)) {
List<String> uppercaseLines = transformStream
.map(String::toUpperCase)
.collect(Collectors.toList());
uppercaseLines.forEach(System.out::println);
}
// Clean up
Files.deleteIfExists(tempFile);
} catch (IOException e) {
e.printStackTrace();
}
// Reading from classpath resource
System.out.println("\n=== Reading from Classpath ===");
try (InputStream is = FileStreams.class.getResourceAsStream("/data.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
Stream<String> classpathStream = reader.lines();
classpathStream.limit(3).forEach(System.out::println);
} catch (Exception e) {
System.out.println("Resource not found: " + e.getMessage());
}
}
}
BufferedReader.lines()
import java.io.*;
import java.util.*;
import java.util.stream.*;
public class BufferedReaderStreams {
public static void main(String[] args) {
String text = "First Line\nSecond Line\nThird Line\nFourth Line\nFifth Line";
// Using BufferedReader with StringReader
try (StringReader stringReader = new StringReader(text);
BufferedReader bufferedReader = new BufferedReader(stringReader)) {
Stream<String> linesStream = bufferedReader.lines();
System.out.println("=== All Lines ===");
linesStream.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
// Processing with filters
try (StringReader stringReader = new StringReader(text);
BufferedReader bufferedReader = new BufferedReader(stringReader)) {
System.out.println("\n=== Lines containing 'Second' ===");
bufferedReader.lines()
.filter(line -> line.contains("Second"))
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
7. Stream Concatenation
Stream.concat()
import java.util.*;
import java.util.stream.*;
public class StreamConcatenation {
public static void main(String[] args) {
// Concatenating two streams
Stream<String> stream1 = Stream.of("A", "B", "C");
Stream<String> stream2 = Stream.of("D", "E", "F");
Stream<String> concatenated = Stream.concat(stream1, stream2);
System.out.println("Concatenated: " + concatenated.collect(Collectors.toList()));
// Concatenating multiple streams
Stream<Integer> numbers1 = Stream.of(1, 2, 3);
Stream<Integer> numbers2 = Stream.of(4, 5, 6);
Stream<Integer> numbers3 = Stream.of(7, 8, 9);
Stream<Integer> allNumbers = Stream.concat(
Stream.concat(numbers1, numbers2), numbers3
);
System.out.println("All numbers: " + allNumbers.collect(Collectors.toList()));
// Concatenating with different types (using map)
Stream<String> stringStream = Stream.of("1", "2", "3");
Stream<Integer> intStream = Stream.of(4, 5, 6);
Stream<Integer> mixedConcatenated = Stream.concat(
stringStream.map(Integer::parseInt), intStream
);
System.out.println("Mixed concatenated: " + mixedConcatenated.collect(Collectors.toList()));
// Practical example - merging data from different sources
List<String> databaseResults = Arrays.asList("DB1", "DB2", "DB3");
List<String> apiResults = Arrays.asList("API1", "API2");
List<String> fileResults = Arrays.asList("FILE1", "FILE2", "FILE3");
Stream<String> combinedResults = Stream.concat(
databaseResults.stream(),
Stream.concat(apiResults.stream(), fileResults.stream())
);
System.out.println("Combined results: " + combinedResults.collect(Collectors.toList()));
}
}
8. Pattern and String Streams
Pattern.splitAsStream()
import java.util.*;
import java.util.regex.*;
import java.util.stream.*;
public class PatternStreams {
public static void main(String[] args) {
String text = "Apple,Banana,Cherry,Date,Fig,Grape";
// Split string using pattern
Pattern pattern = Pattern.compile(",");
Stream<String> fruitStream = pattern.splitAsStream(text);
System.out.println("Fruits: " + fruitStream.collect(Collectors.toList()));
// Complex pattern matching
String logData = "ERROR: Database connection failed\n" +
"INFO: User logged in\n" +
"WARN: High memory usage\n" +
"ERROR: File not found\n" +
"DEBUG: Processing request";
Pattern errorPattern = Pattern.compile("ERROR:.*", Pattern.MULTILINE);
Stream<String> errorStream = errorPattern.splitAsStream(logData);
System.out.println("\nError messages:");
errorStream.filter(s -> !s.isEmpty())
.forEach(System.out::println);
// Extract specific patterns
String data = "John:25, Alice:30, Bob:35, Charlie:40";
Pattern agePattern = Pattern.compile("(\\w+):(\\d+)");
Stream<String> ageStream = agePattern.splitAsStream(data);
ageStream.filter(s -> !s.isEmpty() && s.contains(","))
.map(s -> s.replace(",", "").trim())
.forEach(System.out::println);
// Using Matcher with stream (alternative approach)
System.out.println("\nUsing Matcher:");
Matcher matcher = agePattern.matcher(data);
matcher.results()
.forEach(matchResult ->
System.out.println(matchResult.group(1) + " is " + matchResult.group(2)));
}
}
String.chars() and String.codePoints()
import java.util.*;
import java.util.stream.*;
public class StringCharacterStreams {
public static void main(String[] args) {
String text = "Hello Java 8 Streams!";
// String.chars() - returns IntStream of char values
System.out.println("=== String.chars() ===");
text.chars()
.forEach(ch -> System.out.print((char) ch + " "));
System.out.println();
// Count vowels using chars()
long vowelCount = text.chars()
.filter(Character::isLetter)
.map(Character::toLowerCase)
.filter(ch -> "aeiou".indexOf(ch) != -1)
.count();
System.out.println("Vowel count: " + vowelCount);
// String.codePoints() - handles Unicode characters properly
System.out.println("\n=== String.codePoints() ===");
String unicodeText = "Hello 🚀 World 🌍";
unicodeText.codePoints()
.forEach(cp -> System.out.print(Character.toChars(cp)));
System.out.println();
// Count code points vs chars
System.out.println("Length by chars(): " + unicodeText.chars().count());
System.out.println("Length by codePoints(): " + unicodeText.codePoints().count());
System.out.println("String length: " + unicodeText.length());
// Convert to Character stream
System.out.println("\n=== Character Stream ===");
Stream<Character> charStream = text.chars()
.mapToObj(ch -> (char) ch);
charStream.forEach(ch -> System.out.print(ch + " "));
System.out.println();
}
}
9. Empty and Single Element Streams
Stream.empty()
import java.util.*;
import java.util.stream.*;
public class EmptyStreams {
public static void main(String[] args) {
// Empty stream
Stream<String> emptyStream = Stream.empty();
System.out.println("Empty stream count: " + emptyStream.count());
// Using empty stream as default
List<String> maybeEmptyList = Collections.emptyList();
Stream<String> safeStream = maybeEmptyList != null ?
maybeEmptyList.stream() : Stream.empty();
System.out.println("Safe stream count: " + safeStream.count());
// Combining with other streams
Stream<String> hasData = Stream.of("A", "B", "C");
Stream<String> noData = Stream.empty();
Stream<String> combined = Stream.concat(hasData, noData);
System.out.println("Combined with empty: " + combined.collect(Collectors.toList()));
// Using in method returns
System.out.println("Search results: " + searchData("valid").collect(Collectors.toList()));
System.out.println("Search results: " + searchData("invalid").collect(Collectors.toList()));
// Empty specialized streams
IntStream emptyIntStream = IntStream.empty();
LongStream emptyLongStream = LongStream.empty();
DoubleStream emptyDoubleStream = DoubleStream.empty();
System.out.println("Empty IntStream sum: " + emptyIntStream.sum());
System.out.println("Empty LongStream count: " + emptyLongStream.count());
System.out.println("Empty DoubleStream average: " +
emptyDoubleStream.average().orElse(0.0));
}
public static Stream<String> searchData(String query) {
if ("valid".equals(query)) {
return Stream.of("Result1", "Result2", "Result3");
} else {
return Stream.empty(); // Better than returning null
}
}
}
10. Advanced Stream Creation Patterns
Custom Stream Sources
import java.util.*;
import java.util.stream.*;
public class CustomStreamSources {
// Custom iterator-based stream
public static Stream<Integer> fibonacciStream(int limit) {
return Stream.iterate(new int[]{0, 1}, fib -> new int[]{fib[1], fib[0] + fib[1]})
.limit(limit)
.map(fib -> fib[0]);
}
// Custom generator with state
public static Stream<String> numberedStream(String prefix, int count) {
AtomicInteger counter = new AtomicInteger(1);
return Stream.generate(() -> prefix + counter.getAndIncrement())
.limit(count);
}
// Stream from custom data structure
static class TreeNode {
String value;
List<TreeNode> children;
TreeNode(String value, TreeNode... children) {
this.value = value;
this.children = Arrays.asList(children);
}
// Depth-first traversal stream
Stream<TreeNode> depthFirst() {
return Stream.concat(
Stream.of(this),
children.stream().flatMap(TreeNode::depthFirst)
);
}
// Breadth-first traversal stream
Stream<TreeNode> breadthFirst() {
return Stream.iterate(
Collections.singletonList(this),
list -> list.stream()
.flatMap(node -> node.children.stream())
.collect(Collectors.toList())
)
.takeWhile(list -> !list.isEmpty())
.flatMap(List::stream);
}
}
public static void main(String[] args) {
System.out.println("=== Custom Fibonacci ===");
fibonacciStream(10).forEach(n -> System.out.print(n + " "));
System.out.println();
System.out.println("\n=== Numbered Stream ===");
numberedStream("Item-", 5).forEach(System.out::println);
System.out.println("\n=== Tree Traversal ===");
TreeNode root = new TreeNode("A",
new TreeNode("B",
new TreeNode("D"),
new TreeNode("E")),
new TreeNode("C",
new TreeNode("F"),
new TreeNode("G"))
);
System.out.println("Depth-first:");
root.depthFirst().map(node -> node.value).forEach(v -> System.out.print(v + " "));
System.out.println("\nBreadth-first:");
root.breadthFirst().map(node -> node.value).forEach(v -> System.out.print(v + " "));
System.out.println();
}
}
Best Practices Summary
import java.util.*;
import java.util.stream.*;
public class StreamCreationBestPractices {
public static void main(String[] args) {
// 1. Prefer collection streams for existing data
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Stream<String> goodStream = names.stream(); // Good
Stream<String> verboseStream = Stream.of("Alice", "Bob", "Charlie"); // Less ideal
// 2. Use appropriate stream type for primitives
int[] numbers = {1, 2, 3, 4, 5};
IntStream efficient = Arrays.stream(numbers); // Good - no boxing
Stream<Integer> inefficient = Stream.of(1, 2, 3, 4, 5); // Boxing overhead
// 3. Close I/O-based streams
try (Stream<String> fileStream = Files.lines(Paths.get("data.txt"))) {
fileStream.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
// 4. Use empty() instead of null
public Stream<String> getData() {
return dataAvailable ? data.stream() : Stream.empty(); // Good
// return dataAvailable ? data.stream() : null; // Bad
}
// 5. Consider parallel streams for CPU-intensive operations
List<Integer> largeList = // ... large collection
largeList.parallelStream() // Good for CPU-bound tasks
.map(x -> expensiveOperation(x))
.collect(Collectors.toList());
// 6. Use builder for complex stream construction
Stream.Builder<String> builder = Stream.builder();
if (condition1) builder.add("A");
if (condition2) builder.add("B");
if (condition3) builder.add("C");
Stream<String> complexStream = builder.build();
// 7. Prefer method references in stream pipelines
names.stream().map(String::toUpperCase); // Good
names.stream().map(s -> s.toUpperCase()); // Okay, but verbose
}
}
Key Points Summary
- Collection Streams:
collection.stream(),collection.parallelStream() - Array Streams:
Arrays.stream(),Stream.of() - Factory Methods:
Stream.generate(),Stream.iterate(),Stream.builder() - I/O Streams:
Files.lines(),BufferedReader.lines() - Specialized Streams:
IntStream,LongStream,DoubleStream - String Streams:
String.chars(),String.codePoints(),Pattern.splitAsStream() - Empty Streams:
Stream.empty()for safe API design - Concatenation:
Stream.concat()for combining streams
Stream creation is the foundation of stream processing in Java, and understanding these various creation methods enables you to work with data from diverse sources efficiently.