TGViewer
Java: fill the gaps Java: fill the gaps @java_fillthegaps · 12.3K subscribers
Post #547 17.3K
Java 22: изменения в Stream API (с плохим API)

19 марта выйдет Java 22. Там появится интересная превью фича Stream Gatherers. Коротко расскажу, что это, зачем нужно, и что с ней не так.

Начнём. Код со Stream API делится на 3 части:
▫️ источник данных
▫️ промежуточные операции: map, filter, flatMap
▫️ терминальная операция: collect, count, findAny

Промежуточных операций немного, но они легко покрывают большую часть задач.

Иногда их недостаточно. Например, хочется сделать distinct по какому-то признаку и дальше работать с исходными объектами:
clients.stream()
.distinct(Client::getBonusType)
.map(Client::getId).forEach(…)


Но это невозможно, distinct работает только по equals. В итоге надо либо извращаться, либо переписывать на for.

В Java 22 в Stream API появится универсальный метод gather. Туда можно передать логику преобразований с любыми отношениями - 1:1, 1:N, N:1, N:N. Синтаксис сложный, но круто, что такая возможность появилась.

Второе нововведение. Для collect есть готовые статические методы в классе Collectors, а для gather появится Gatherers с новыми методами. Самое полезное — два метода по работе с окнами:

🪟 windowFixed — поделить стрим на подмножества заданного размера
[1,2,3,4,5,6] → windowFixed(3) → [1,2,3], [4,5,6]


🪟 windowSliding — подмножества с пересечением одного элемента
[1,2,3,4,5,6,7] → windowSliding(3) → [1,2,3], [3,4,5], [5,6,7]


Что не так c методом gather?

1️⃣ Многословность

Та же ситуация, что и с collect. Чтобы разбить список на окна, придётся написать
list.stream()
.gather(Gatherers.windowFixed(2))
.collect(Collectors.toList())


Даже со статическим импортом выглядит не очень. Хочется писать без лишних слов:
list.stream()
.windowFixed(2)
.toList()


Да, исходный код Stream API сложный, и его тяжело расширять. Да, через статические методы реализация получится проще. Но не вижу ничего невозможного, чтобы сделать новые методы лаконичными, без приставки "gather(Gatherers"

2️⃣ Странные новые методы

Начнём с оконных. windowSliding делает пересечение только по одному элементу. Зачем нужно это ограничение — непонятно. Так же непонятно, зачем делать два отдельных метода windowFixed и windowSliding.

За образец можно взять Kotlin:
list.windowed(5,2)


Первый параметр задаёт размер окна, второй — шаг, с которым идём по списку. Удобно и понятно.

Ещё в Gatherers появятся три странных метода: fold, mapConcurrent и scan. С первого взгляда непонятно, зачем они нужны, очень уж специфичны.

В целом криминала в gather/Gatherers нет, жить можно. Но важный навык разработчика — замечать слабые места в своих и чужих решениях. Этот навык нужно развивать, для этого и нужен этот пост:)

Что ещё почитать:
🔥 Серия постов про коллекторы. Там же я рассказала, почему в стримах используется отдельный метод collect, а не просто toList()
🔥 Новые методы Stream API в Java 16
🔥 Критикую метод HashMap в Java 20. Хотя сам метод маленький, он показывает серьёзную ошибку проектирования API
  • 🔥 126
  • 👍 69
  • ❤ 23
  • 👎 7
More from @java_fillthegaps
  1. Apr 30, 2026Get Your Hands Dirty on Clean Architecture: отзыв на книгу Когда я подняла тему чистой арх…
  2. Apr 27, 2026​Clean Architecture: отзыв на книгу Наконец-то дочитала книгу Clean Architecture Роберта М…
  3. Mar 4, 2026Как переиспользовать контекст в интеграционных тестах Сегодня расскажу базовый минимум для…
  4. Mar 4, 2026Post #660
  5. Mar 4, 2026Тестовый контекст поднимается 2 минуты. У нас 4 класса с интеграционными тестами, их конфи…
  6. Feb 25, 2026Чистая архитектура. Главы 3-5 Продолжаем спидран по Clean Architecture Роберта Мартина. ⭐️…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →