← Назад к вопросам
Какие знаешь способы инициализации Stream?
2.0 Middle🔥 121 комментариев
#Stream API и функциональное программирование
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Способы инициализации Stream
Stream API предоставляет множество способов создания потоков из различных источников данных. Правильный выбор способа инициализации влияет на производительность и удобство использования.
1. Из коллекций (Collections)
Из List
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Создание Stream из List
Stream<String> stream = names.stream();
stream.forEach(System.out::println);
// Параллельный Stream (для больших коллекций)
Stream<String> parallelStream = names.parallelStream();
parallelStream
.filter(name -> name.length() > 3)
.forEach(System.out::println);
Из Set
Set<Integer> numbers = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
Stream<Integer> stream = numbers.stream();
long count = stream.count(); // 5
Из Map
Map<String, Integer> ages = new HashMap<>();
ages.put("Alice", 25);
ages.put("Bob", 30);
ages.put("Charlie", 22);
// Stream ключей
Stream<String> keys = ages.keySet().stream();
// Stream значений
Stream<Integer> values = ages.values().stream();
// Stream пар (Entry)
Stream<Map.Entry<String, Integer>> entries = ages.entrySet().stream();
entries
.filter(entry -> entry.getValue() > 25)
.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
2. Из массивов (Arrays)
String[] fruits = {"apple", "banana", "cherry"};
// Способ 1: Arrays.stream()
Stream<String> stream1 = Arrays.stream(fruits);
// Способ 2: Stream.of()
Stream<String> stream2 = Stream.of(fruits);
// Способ 3: С указанием диапазона
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
IntStream range = Arrays.stream(numbers, 2, 7); // Элементы с индекса 2 до 7
range.forEach(System.out::println); // 3, 4, 5, 6, 7
// Для примитивных типов
int[] intArray = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(intArray);
int sum = intStream.sum();
long[] longArray = {1L, 2L, 3L};
LongStream longStream = Arrays.stream(longArray);
double[] doubleArray = {1.5, 2.5, 3.5};
DoubleStream doubleStream = Arrays.stream(doubleArray);
3. Из диапазонов (Ranges)
// Диапазон целых чисел
IntStream range = IntStream.range(1, 5); // 1, 2, 3, 4 (исключительно 5)
range.forEach(System.out::println);
// Диапазон с включением верхней границы
IntStream rangeClosed = IntStream.rangeClosed(1, 5); // 1, 2, 3, 4, 5
rangeClosed.forEach(System.out::println);
// Для больших диапазонов
LongStream longRange = LongStream.range(1, 1_000_000_000);
long count = longRange.count(); // 999_999_999
// Практический пример: цены с 10 до 100
IntStream prices = IntStream.rangeClosed(10, 100)
.filter(price -> price % 10 == 0); // Кратные 10
4. Из строк (String)
String text = "Hello, World!";
// Поток символов
IntStream charStream = text.chars(); // Возвращает коды символов
charStream.forEach(c -> System.out.print((char) c));
// Поток кодовых точек Unicode (для emoji и специальных символов)
IntStream codePointStream = text.codePoints();
// Поток слов (с регулярным выражением)
String sentence = "The quick brown fox jumps over the lazy dog";
Stream<String> words = Pattern.compile("\\s+").splitAsStream(sentence);
words
.filter(word -> word.length() > 3)
.forEach(System.out::println);
5. Из файлов (Files)
import java.nio.file.*;
// Stream строк из файла
Stream<String> lines = Files.lines(Paths.get("data.txt"));
lines
.filter(line -> !line.isEmpty())
.forEach(System.out::println);
// Stream файлов в директории
Stream<Path> files = Files.list(Paths.get("/home/user/documents"));
files
.filter(Files::isRegularFile)
.filter(path -> path.toString().endsWith(".txt"))
.forEach(System.out::println);
// Рекурсивный обход директории
Stream<Path> allFiles = Files.walk(Paths.get("/home/user/documents"))
.filter(Files::isRegularFile);
allFiles.forEach(System.out::println);
// Поток строк из файла (try-with-resources)
try (Stream<String> stream = Files.lines(Paths.get("data.txt"))) {
long emptyLines = stream.filter(String::isEmpty).count();
System.out.println("Empty lines: " + emptyLines);
}
6. Stream.of() — явное создание
// Из отдельных элементов
Stream<String> stream1 = Stream.of("apple", "banana", "cherry");
// Из массива
Stream<String> stream2 = Stream.of("apple", "banana", "cherry");
stream2.forEach(System.out::println);
// Пустой Stream
Stream<String> emptyStream = Stream.empty();
long count = emptyStream.count(); // 0
// Конкатенация потоков
Stream<String> stream3 = Stream.of("apple", "banana");
Stream<String> stream4 = Stream.of("cherry", "date");
Stream<String> combined = Stream.concat(stream3, stream4);
combined.forEach(System.out::println); // apple, banana, cherry, date
7. Генерирование потоков (Generators)
// Stream.generate() — бесконечный поток одного значения
Stream<Double> randomNumbers = Stream.generate(Math::random)
.limit(5);
randomNumbers.forEach(System.out::println);
// Stream.iterate() — итерирование с функцией
Stream<Integer> iterations = Stream.iterate(0, n -> n + 2) // 0, 2, 4, 6, ...
.limit(5);
iterations.forEach(System.out::println); // 0, 2, 4, 6, 8
// Фибоначчи
Stream.iterate(new int[]{0, 1}, arr -> new int[]{arr[1], arr[0] + arr[1]})
.limit(10)
.map(arr -> arr[0])
.forEach(System.out::println);
// Stream.generate() с Supplier
Stream<String> ids = Stream.generate(() -> UUID.randomUUID().toString())
.limit(3);
ids.forEach(System.out::println);
8. Из опциональных значений (Optional)
Optional<String> optional = Optional.of("Hello");
// Stream из Optional (Java 9+)
Stream<String> stream = optional.stream();
stream.forEach(System.out::println); // Hello
// Если Optional пусто
Optional<String> empty = Optional.empty();
Stream<String> emptyStream = empty.stream();
long count = emptyStream.count(); // 0
// Практический пример
Optional<User> user = userRepository.findById(1L);
user.stream()
.filter(u -> u.isActive())
.map(User::getEmail)
.forEach(email -> sendEmail(email));
9. Из лямбда-выражений и функций
// Собственный поток через Supplier
Stream<String> customStream = Stream.generate(() -> {
// Генерируем случайные строки
return "Item_" + System.nanoTime();
}).limit(5);
customStream.forEach(System.out::println);
// Итерирование с условием (Java 9+)
Stream<Integer> sequence = Stream.iterate(
1,
n -> n < 100, // Условие продолжения
n -> n * 2 // Функция следующего элемента
);
sequence.forEach(System.out::println); // 1, 2, 4, 8, 16, 32, 64
10. Из других Stream API
// flatMap для развертывания
List<List<Integer>> lists = Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5, 6)
);
Stream<Integer> flattened = lists.stream()
.flatMap(List::stream);
flattened.forEach(System.out::println);
// Из BufferedReader
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
Stream<String> lines = reader.lines();
lines
.filter(line -> line.startsWith("#")) // Комментарии
.forEach(System.out::println);
reader.close();
Сравнение методов
List<String> list = Arrays.asList("a", "b", "c");
// Способ 1: list.stream()
list.stream().forEach(System.out::println);
// Способ 2: Stream.of()
Stream.of("a", "b", "c").forEach(System.out::println);
// Способ 3: Из массива
Stream.of(list.toArray(new String[0])).forEach(System.out::println);
// Способ 1 — оптимален для коллекций
// Способ 2 — удобен для нескольких элементов
// Способ 3 — редко требуется
Важные моменты
- Параллельные потоки (parallelStream) полезны для больших наборов данных
- Stream одноразовые — после терминальной операции нельзя переиспользовать
- Ленивое вычисление — промежуточные операции выполняются только при терминальной операции
- Ресурсы — потоки из файлов и читателей нужно закрывать
Правильный выбор способа инициализации Stream — первый шаг к эффективной обработке данных в Java.