Страницы

Поиск по вопросам

суббота, 27 октября 2018 г.

Java 8 stream map to new Objects

Как можно замапить стрим в новые объекты? Или, эти примеры что не равнозначны?
list.stream().map(new SomeObject()::convertToSomeObject)
list.stream().map(item -> new SomeObject().convertToSomeObject(item))
public SomeObject convertToSomeObject(Item item) { this.name = item.getName; this.value = item.getValue; return this; }
в первом случае у меня все замапилось одним объектом


Ответ

Почему не работает первый вариант
При выполнении строчки
list.stream().map(new SomeObject()::convertToSomeObject)
происходит следующее:
до вызова метода map создаётся новый объект SomeObject ссылка на метод этого объекта передаётся в качестве параметра-лямбды в метод map берутся по очереди все элементы старого потока, к ним применяется переданный метод из полученных в результате применения метода новых объектов создаётся новый поток
Здесь объект SomeObject создаётся ровно один раз, и так как его метод convertToSomeObject всегда возвращает единственный созданный экземпляр, то и получается, что новый поток состоит из ссылок на один и тот же объект. При этом метод convertToSomeObject вызывался для каждого элемента потока и каждый раз значения полей объекта перезаписывались
Почему работает второй варинат
При выполнении строчки
list.stream().map(item -> new SomeObject().convertToSomeObject(item))
происходит следующее:
никаких объектов SomeObject до вызова map не создаётся в метод map передаётся лямбда-функция, которая работает как обычная функция:
принимает объект item создаёт новый экземпляр класса SomeObject вызывает метод convertToSomeObject у созданного экземпляра возвращает результат вызова метода convertToSomeObject, то есть только что созданный экземпляр класса SomeObject заметим, что лямбда-функция создаёт новый объект при каждом вызове
Как исправить первый вариант
написать конструктор SomeObject, принимающий Item в качестве параметра:
public SomeObject(Item item) { this.name = item.getName(); }
list.stream().map(SomeObject::new) добавить в класс SomeObject статический метод, принимающий Item и возвращающий SomeObject
public static SomeObject convertToSomeObject(Item item) { SomeObject object = new SomeObject(); object.name = item.getName(); return object; }
list.stream().map(SomeObject::convertToSomeObject) Перенести метод convertToSomeObject в класс Item
public SomeObject convertToSomeObject() { SomeObject object = new SomeObject(); object.name = this.getName(); return object; }
list.stream().map(Item::convertToSomeObject)

Комментариев нет:

Отправить комментарий