[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-java-11-25-chto-novogo-v-stream-api-ot-java-11-do-java-25":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":16,"progress":17,"seo":18},419,"chto-novogo-v-stream-api-ot-java-11-do-java-25",11,"java-11-25","Java 11–25","🆕","Что нового в Stream API от Java 11 до Java 25?","Stream API эволюционировал от добавления `toList()` (Java 16) и `mapMulti()` до полноценных расширяемых промежуточных операций через Stream Gatherers (Java 24\u002F25).\n\n### Эволюция Stream API\n\n| Версия | Нововведение | Описание |\n|--------|-------------|----------|\n| Java 16 | `toList()` | Неизменяемый список, замена `collect(Collectors.toList())` |\n| Java 16 | `mapMulti()` | Замена flatMap для простых случаев (0-N результатов) |\n| Java 24\u002F25 | Stream Gatherers | Пользовательские промежуточные операции |\n\n\u003Cdetails>\u003Csummary>Пример: toList(), mapMulti()\u003C\u002Fsummary>\n\n```java\n\u002F\u002F Java 16: Stream.toList() — неизменяемый список\nList\u003CString> names = users.stream()\n    .map(User::getName)\n    .toList(); \u002F\u002F вместо .collect(Collectors.toList())\n\n\u002F\u002F Java 16: Stream.mapMulti() — замена flatMap для простых случаев\nStream.of(1, 2, 3, 4)\n    .\u003CInteger>mapMulti((n, consumer) -> {\n        if (n % 2 == 0) {\n            consumer.accept(n);\n            consumer.accept(n * 10);\n        }\n    })\n    .toList(); \u002F\u002F [2, 20, 4, 40]\n```\n\n\u003C\u002Fdetails>\n\n### Stream Gatherers (Java 24\u002F25)\n\nGatherers позволяют создавать stateful промежуточные операции — то, что ранее было невозможно стандартными средствами Stream API.\n\n```java\n\u002F\u002F Встроенные Gatherers:\n\u002F\u002F windowFixed — фиксированные окна\nList\u003CList\u003CInteger>> windows = Stream.of(1, 2, 3, 4, 5, 6)\n    .gather(Gatherers.windowFixed(3))\n    .toList(); \u002F\u002F [[1, 2, 3], [4, 5, 6]]\n\n\u002F\u002F windowSliding — скользящее окно\nList\u003CList\u003CInteger>> sliding = Stream.of(1, 2, 3, 4, 5)\n    .gather(Gatherers.windowSliding(3))\n    .toList(); \u002F\u002F [[1, 2, 3], [2, 3, 4], [3, 4, 5]]\n\n\u002F\u002F scan — промежуточные результаты свёртки\nList\u003CInteger> runningSum = Stream.of(1, 2, 3, 4, 5)\n    .gather(Gatherers.scan(() -> 0, Integer::sum))\n    .toList(); \u002F\u002F [1, 3, 6, 10, 15]\n\n\u002F\u002F mapConcurrent — параллельная обработка с Virtual Threads\nList\u003CString> results = urls.stream()\n    .gather(Gatherers.mapConcurrent(10, url -> fetchUrl(url)))\n    .toList(); \u002F\u002F до 10 параллельных запросов\n```\n\n\u003Cdetails>\u003Csummary>Пример: custom Gatherer — distinctBy\u003C\u002Fsummary>\n\n```java\n\u002F\u002F Пример: distinctBy — unique по ключу\nstatic \u003CT, K> Gatherer\u003CT, ?, T> distinctBy(Function\u003CT, K> keyExtractor) {\n    return Gatherer.ofSequential(\n        HashSet\u003CK>::new,\n        (state, element, downstream) -> {\n            K key = keyExtractor.apply(element);\n            if (state.add(key)) {\n                return downstream.push(element);\n            }\n            return true;\n        }\n    );\n}\n\n\u002F\u002F Использование:\nusers.stream()\n    .gather(distinctBy(User::getEmail))\n    .toList();\n```\n\n\u003C\u002Fdetails>\n\n### Частые ошибки\n\n- Мутация списка из `toList()` — `UnsupportedOperationException`; если нужен мутабельный — `collect(Collectors.toList())`\n- `mapConcurrent` для CPU-bound — Virtual Threads не ускоряют CPU-bound; используйте `parallelStream()`\n- Custom Gatherer без proper state management — Gatherer может быть parallel; state должен быть thread-safe или sequential\n\n### Как используется в 2026\n\n- `toList()` — повсеместно заменяет `collect(Collectors.toList())`\n- Gatherers — новый инструмент для сложных потоковых обработок (окна, группировки, stateful)\n- `mapConcurrent` — удобная параллелизация I\u002FO-задач в stream\n\n> **На собеседовании:** обязательно знайте разницу `toList()` vs `collect(Collectors.toList())` (иммутабельность). Для middle+ уровня — расскажите про Gatherers: windowFixed\u002FwindowSliding для оконных операций и mapConcurrent для параллельного I\u002FO с Virtual Threads.","","middle",[15],"java-modern",[],null,{"title":19,"description":20,"ogTitle":19,"ogDescription":21,"keywords":22,"schemaAnswer":23,"featuredSnippetReady":24},"Что нового в Stream API от Java 11 до Java 25? — Gymterview","Stream API эволюционировал от добавления `toList()` (Java 16) и `mapMulti()` до полноценных расширяемых промежуточных операций через Stream Gatherers (Java 24\u002F2","Stream API эволюционировал от добавления `toList()` (Java 16) и `mapMulti()` до полноценных расширяемых промежуточных оп",[15,13],"Stream API эволюционировал от добавления `toList()` (Java 16) и `mapMulti()` до полноценных расширяемых промежуточных операций через Stream Gatherers (Java 24\u002F25).",true]