В чем отличие методов map и flatMap в Java Streams
Что проверяют
Понимаете ли вы, что flatMap разворачивает вложенность, и умеете ли привести случай, где map даёт стрим стримов.
Как отвечать
map преобразует каждый элемент в другой: один вход, один выход. flatMap преобразует элемент в поток и склеивает все полученные потоки в один: один вход, ноль или больше выходов.
List<Order> orders = ...;
Stream<List<Item>> wrong = orders.stream().map(Order::getItems); // поток списков
Stream<Item> right = orders.stream().flatMap(o -> o.getItems().stream()); // поток товаровОтсюда практические применения flatMap: развернуть вложенные коллекции, разбить строку на слова, отфильтровать и преобразовать одновременно (возвращая пустой поток вместо элемента), развернуть Optional через stream().
Полезно упомянуть, что то же самое есть у Optional: map даст Optional<Optional<T>>, если функция сама возвращает Optional, а flatMap вернёт плоский. Логика одна и та же в обоих случаях.
С Java 16 есть mapMulti: тот же разворот, но без создания промежуточного потока на каждый элемент. На больших объёмах бывает заметно быстрее.
Где спотыкаются
Не могут объяснить, откуда берётся Stream<Stream<T>>.
Забывают вызвать .stream() внутри flatMap и получают ошибку компиляции.
Не знают про flatMap у Optional и пишут вложенные проверки.
Считают flatMap фильтром: он разворачивает, а фильтрация это побочный эффект возврата пустого потока.