← Назад к вопросам

Какие знаешь способы инициализации 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.