JavaRush/Курсы/Java Syntax Pro/Работа с потоками, часть 2

Работа с потоками, часть 2

Открыта

1. Преобразование данных

Также у класса Stream<T> есть метод, который позволяет преобразовать данные из одного типа в другой. Этот метод называется map().

Он тоже возвращает поток Stream<R>, но уже с элементами нового типа. В качестве параметра в метод map() нужно передать функцию, которая преобразовывает один тип данных в другой.

Примеры:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<String> stream2 = stream.map((x) -> String.valueOf(x));
Преобразовываем поток Integer в поток String

Функция, которую передали в метод map() в качестве параметра, принимает число x, а в качестве результата возвращает строку. Можно, кстати, записать этот код короче:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<String> stream2 = stream.map(String::valueOf);
Преобразовываем поток Integer в поток String

Преобразование строки в число

Аналогично можно написать код и для преобразования строки в число — тоже ничего сложного:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<String> stream2 = stream.map(String::valueOf);
Stream<Integer> stream3 = stream2.map(Integer::parseInt);
Преобразовываем поток String в поток Integer

Преобразование строки в URI

Операции по преобразованию данных могут быть большими и тяжелыми. Допустим, мы хотим преобразовать коллекцию строк в объекты URI. Это очень легко сделать, ведь URI принимает строку в качестве параметра конструктора

ArrayList<String> list = new ArrayList<String>();
list.add("https://google.com");
list.add("https://linkedin.com");
list.add("https://yandex.com");

Stream<URI> stream = list.stream().map( URI::new );
Преобразовываем поток String в поток URI

Мы создали коллекцию, записали в нее 3 ссылки на сайты в интернете. Затем получили у коллекции объект Stream<String> и у него — объект Stream<URI>. А в метод map передали ссылку на метод, который будет использоваться для преобразования из String в URI.

Этот метод (конструктор) должен принимать в качестве параметра тип String. Все вроде бы идеально...


2. Исключения

Код выше должен работать, но он работать не будет — программа не скомпилируется. И не потому, что мы где-то сделали ошибку, а потому, что ее сделали разработчики Java.

Когда-то давно им пришла в голову замечательная идея — добавить в конструктор(!) класса URI checked-исключение URISyntaxException. А такие исключения нужно обязательно заворачивать в try-catch.

Поэтому последняя строка нашего кода будет выглядеть вот так:

Stream<URI> stream = list.stream().map(str ->
{
  try
  {
     return new URI(str);
  }
  catch (URISyntaxException e)
  {
     e.printStackTrace();
     return null;
  }
});

Что вам сказать? Нужно дважды подумать, прежде чем использовать checked-исключения. И трижды, прежде чем использовать их в конструкторе.


Комментарии (120)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Euraks Backend Developer
9 октября, 04:07
🦔
Grigoryvvv
Уровень 28
Expert
29 июля, 21:46
30.07.2026 / 19 уровень
Anton Pohodin
Уровень 27
29 декабря 2025, 05:49
Когда я проходил курс Java 25 SELF - было веселее, т.к. мало что понимал в ссылках на методы и еще хуже знал как их формировать. Но теперь уже всё легко, особенно, когда знаешь, как превратить лямбда-выражение в ссылку на метод. Не всегда, но примерно в 85% случаях это работает.
LisoEdoEdГлавный инженер-геодезист в ЗапСибГазпромStudent
14 декабря 2025, 18:37
Ништяк
Виктор
Уровень 28
4 октября 2025, 07:46
Начинаю немного понимать что к чему) или нет.
Anonymous #3585174
Уровень 33
23 июля 2025, 18:41
like
ShadyLine
Уровень 51
8 апреля 2025, 12:43
сложно
Cryptosin Crypto Magnat
23 февраля 2025, 16:47
Отличие между map() и flatMap() Представим, что у нас есть список людей и их списки хобби:
List<Person> people = List.of(
    new Person("Аня", List.of("Плавание", "Чтение")),
    new Person("Борис", List.of("Шахматы", "Рисование")),
    new Person("Вика", List.of("Танцы"))
);
Где Person — это просто класс:
class Person {
    String name;
    List<String> hobbies;

    Person(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }
}
1️⃣ map(): Получаем список списков хобби
List<List<String>> hobbiesList = people.stream()
    .map(person -> person.hobbies)
    .toList();

System.out.println(hobbiesList);
💡 Вывод:
[
    [Плавание, Чтение],
    [Шахматы, Рисование],
    [Танцы]
]
👉 Мы получили список списков, то есть список, где у каждого человека свой отдельный список хобби. 2️⃣ flatMap(): Получаем просто список всех хобби
List<String> allHobbies = people.stream()
    .flatMap(person -> person.hobbies.stream())
    .toList();

System.out.println(allHobbies);
💡 Вывод:
[Плавание, Чтение, Шахматы, Рисование, Танцы]
👉 Мы получили простой список всех хобби, потому что flatMap() "разгладил" список списков. 🚀 Разница в одном предложении: - map() оставляет список списков (List<List<String>>). - flatMap() делает один общий список (List<String>).
RustamJava Developer в t.me/jroom_chatStudent
19 октября 2024, 16:41
После стремного кода с try - catch, я ожидал ещё одно включение, где нам расскажут про легкий способ, сделать это всё в 1 строку. Избаловали...
Даниил
Уровень 35
7 февраля 2025, 16:57
URI.create(String);
Anton
Уровень 1
30 сентября 2024, 16:58
return strings.map(String::toUpperCase) Что обозначает символ :: ?
Viktoryia Ka
Уровень 106
6 октября 2024, 11:40
Ссылка на метод. В конкретном примере говорит, что к объекту типа String будет применен метод toUpperCase(). А-ля тернарный оператор, но т к ":" уже зарезервировано для него, то используется "::"