← Назад к вопросам
В каком интерфейсе содержится Stream
1.7 Middle🔥 231 комментариев
#Stream API и функциональное программирование
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
В каком интерфейсе содержится Stream
Stream API — один из самых важных дополнений в Java 8. Stream находится в интерфейсе java.util.stream.Stream<T>, но это не случайно расположенный класс — это часть функционально-ориентированного API Java.
Где находится Stream
import java.util.stream.Stream; // Базовый интерфейс Stream
import java.util.stream.IntStream; // Для примитивов int
import java.util.stream.LongStream; // Для примитивов long
import java.util.stream.DoubleStream; // Для примитивов double
Stream — это интерфейс, а не класс. Его реализацию создают различные источники данных:
java.util.Collection(через методstream())java.util.stream.IntStream,LongStream,DoubleStream(для примитивов)- Массивы (через
Arrays.stream()) - Файлы (через
Files.lines()) - Другие источники
Как создать Stream
1. Из Collection (через Iterable)
Основной способ — через метод stream() в интерфейсе Iterable<T>:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Создание Stream из List
Stream<String> stream = names.stream();
// Обработка
stream.filter(name -> name.startsWith("A"))
.forEach(System.out::println);
// Вывод: Alice
При этом Collection наследует от Iterable, и в Java 8+ добавлен default метод stream():
// В интерфейсе Iterable<E>
public interface Iterable<T> {
Iterator<T> iterator();
// Default метод, добавленный в Java 8
default Stream<T> stream() {
return StreamSupport.stream(
Spliterator.spliterator(this, Spliterator.ORDERED),
false
);
}
}
2. Из массивов
int[] numbers = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(numbers);
String[] words = {"Java", "Stream", "API"};
Stream<String> stringStream = Arrays.stream(words);
Double[] decimals = {1.5, 2.7, 3.2};
Stream<Double> doubleStream = Arrays.stream(decimals);
3. Создание Stream явно
// Пустой Stream
Stream<String> empty = Stream.empty();
// Stream из элементов
Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5);
// Stream из одного элемента
Stream<String> single = Stream.of("Hello");
// Бесконечный Stream (с limit)
Stream<Long> infinite = Stream.iterate(0L, n -> n + 1).limit(10);
// Генерирующий Stream
Stream<Double> generated = Stream.generate(Math::random).limit(5);
4. Из файлов
import java.nio.file.Files;
import java.nio.file.Paths;
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
lines.filter(line -> !line.isEmpty())
.forEach(System.out::println);
}
5. Из Pattern.splitAsStream()
import java.util.regex.Pattern;
String text = "Java,Stream,API";
Pattern.compile(",")
.splitAsStream(text)
.forEach(System.out::println);
Иерархия Stream интерфейсов
// Главный интерфейс для reference types
public interface Stream<T> extends BaseStream<T, Stream<T>> {
// Промежуточные операции (lazy)
Stream<T> filter(Predicate<? super T> predicate);
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
Stream<T> distinct();
Stream<T> sorted();
// Терминальные операции (eager)
void forEach(Consumer<? super T> action);
long count();
Optional<T> findFirst();
Optional<T> findAny();
boolean anyMatch(Predicate<? super T> predicate);
Object[] toArray();
// ... и другие
}
// Специализированные для примитивов
public interface IntStream extends BaseStream<Integer, IntStream> {
IntStream filter(IntPredicate predicate);
IntStream map(IntUnaryOperator mapper);
// ...
}
Полный пример работы со Stream
import java.util.List;
import java.util.stream.Collectors;
public class StreamExample {
public static void main(String[] args) {
List<Person> people = List.of(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35),
new Person("Diana", 28)
);
// Промежуточные операции (ленивые)
// Каждая операция возвращает новый Stream
var result = people.stream()
.filter(p -> p.getAge() >= 30) // Filter
.map(Person::getName) // Map
.sorted() // Sort
.collect(Collectors.toList()); // Терминальная операция
System.out.println(result); // [Alice, Charlie]
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
Промежуточные vs Терминальные операции
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// ПРОМЕЖУТОЧНЫЕ (ленивые) - возвращают Stream
Stream<String> filtered = names.stream() // Stream<String>
.filter(n -> n.length() > 3); // Stream<String>
// .map(String::toUpperCase) // Stream<String>
// Операция ещё не выполнена!
// ТЕРМИНАЛЬНЫЕ (жадные) - выполняют всю цепочку
long count = filtered.count(); // Теперь выполняется!
// Пример с явной ленивостью
var stream = names.stream()
.peek(n -> System.out.println("Seen: " + n)) // Не выполнится!
.filter(n -> n.length() > 3);
// Терминальная операция - только теперь выполнится
stream.forEach(System.out::println); // Видим "Seen: ..." и результат
Параллельные Stream
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Последовательный Stream (default)
Stream<Integer> sequential = numbers.stream();
// Параллельный Stream
Stream<Integer> parallel = numbers.parallelStream();
// Пример использования
int sum = numbers.parallelStream()
.filter(n -> n % 2 == 0) // Четные числа
.mapToInt(Integer::intValue) // IntStream
.sum();
System.out.println(sum); // 2 + 4 + 6 + 8 + 10 = 30
Специализированные Streams для примитивов
// IntStream
IntStream intStream = IntStream.range(1, 5); // 1, 2, 3, 4
intStream.forEach(System.out::println);
// LongStream
LongStream longStream = LongStream.rangeClosed(1, 5); // 1 to 5 inclusive
longStream.sum();
// DoubleStream
DoubleStream doubleStream = DoubleStream.of(1.1, 2.2, 3.3);
doubleStream.average();
// Boxing/Unboxing
Stream<Integer> boxed = IntStream.range(1, 5).boxed();
IntStream unboxed = Stream.of(1, 2, 3).mapToInt(Integer::intValue);
Практические примеры
// 1. Фильтрация и трансформация
List<String> result = names.stream()
.filter(n -> n.startsWith("A"))
.map(String::toUpperCase)
.collect(Collectors.toList());
// 2. Группирование
Map<Integer, List<Person>> byAge = people.stream()
.collect(Collectors.groupingBy(Person::getAge));
// 3. Партиция (разделение на две группы)
Map<Boolean, List<Person>> adults = people.stream()
.collect(Collectors.partitioningBy(p -> p.getAge() >= 18));
// 4. Объединение Stream
Stream<String> combined = Stream.concat(
names.stream(),
Stream.of("Extra")
);
// 5. FlatMap для "развёртывания"
List<List<Integer>> lists = List.of(
List.of(1, 2),
List.of(3, 4),
List.of(5, 6)
);
Stream<Integer> flat = lists.stream().flatMap(List::stream);
Ключевые моменты
- Stream находится в
java.util.streamпакете — не вjava.util - Stream не хранит данные — это lazy pipeline обработки
- Stream можно использовать только один раз — после терминальной операции поток закончен
- По умолчанию Sequential — используй
parallelStream()для параллельной обработки - Ленивые операции — не выполняются до терминальной операции
Заключение
Stream API — это не просто отдельный интерфейс, а целая парадигма функционального программирования, встроенная в Java. Понимание иерархии Stream интерфейсов, способов их создания и операций критично для написания современного Java кода.