в чем разница map и flatmap java
Nurlandroid
Nurlan’s personal website
Show menu Hide menu
My name is Nurlan Nabiyev. I am passionate Android developer. This is my personal website with my portfolio of apps, posts and etc.
Contacts
Phone: +7 705 575 4828
Вникаем в Map, FlatMap, SwitchMap, ConcatMap
Сегодня узнаем подробно о таких операторах как Map, FlatMap, SwitchMap, ConcatMap.
1. Map()
Оператор Map() преобразует каждый элемент, излучаемый Observable-ом, и эмиттит измененный элемент. Мы можем создать цепочку из такого количества Map(), какое посчитаем нужным для того, чтобы придать данным наиболее удобную и простую форму для Observer-a.
Приведем простой пример
Рассмотрите возможность использования оператора Map(), где необходимо выполнить оффлайновые операции с эмитируемыми данными. Например, мы получили что-то от сервера, но это не соответствует нашему требованию. В этом случае Map() может использоваться для изменения эмитируемых данных.
2. FlatMap()
FlatMap() может чередовать элементы при эмиссии, то есть порядок исходящих элементов не поддерживается. Полезен если порядок выполнения не важен, но нужно единовременное выполнение.
3. ConcatMap()
Технически данный оператор выдает похожий с FlatMap() результат, меняется только последовательность эмиттируемых данных. ConcatMap() поддерживает порядок эмиссии данных и ожидает исполнения текущего Observable. Поэтому лучше использовать его когда необходимо обеспечить порядок выполнения задач. При этом нужно помнить, что выполнение ConcatMap() занимает больше времени чем FlatMap().
4. SwithMap()
SwithMap() кардинально отличается от FlatMap() и ConcatMap(). Он лучше всего подходит, если вы хотите проигнорировать промежуточные результаты и рассмотреть последний. SwitchMap отписывается от предыдущего источника Observable всякий раз, когда новый элемент начинает излучать данные, тем самым всегда эмитит данные из текущего Observable.
Чтобы лучше понять давайте приведем пример: Предположим, вы пишете приложение мгновенного поиска, которое отправляет поисковый запрос на сервер каждый раз, когда пользователь что-то вводит в поисковой строке. Пользователь быстро набирает несколько символов. При наборе каждого символа будет отправляться на сервер запрос с дополненной строкой на один символ. Благодаря SwitchMap() мы можем показать результат только последнего набранного запроса.
В чем разница между методами map () и flatMap () в Java 8?
В Java 8, в чем разница Stream.map() и Stream.flatMap() методы?
Это отражено в аргументах каждой операции.
Типичное использование для функции mapper flatMap для возврата, Stream.empty() если она хочет отправить нулевые значения, или что-то вроде, Stream.of(a, b, c) если она хочет вернуть несколько значений. Но, конечно, любой поток может быть возвращен.
Stream.flatMap Как можно догадаться по его названию, это сочетание a map и flat операции. Это означает, что вы сначала применяете функцию к своим элементам, а затем выравниваете ее. Stream.map только применяет функцию к потоку без выравнивания потока.
Я хотел бы привести 2 примера, чтобы получить более практическую точку зрения:
Первый пример, использующий карту:
Ничего особенного в первом примере, a Function применяется для возврата String в верхний регистр.
Второй пример, использующий flatMap :
Во втором примере передается поток списка. Это не поток целых чисел!
Если необходимо использовать функцию преобразования (через карту), то сначала поток должен быть сведен к чему-то другому (поток целых чисел).
Если flatMap удален, то возвращается следующая ошибка: Оператор + не определен для типа (ов) аргумента List, int.
Нельзя применить + 1 к списку целых чисел!
Пожалуйста, пройдите по почте полностью, чтобы получить ясное представление,
карта против плоской карты:
Чтобы вернуть длину каждого слова из списка, мы сделаем что-то вроде ниже.
Короткая версия приведена ниже
Когда мы собираем два списка, приведенных ниже
Без плоской карты => [1,2], [1,1] => [[1,2], [1,1]] Здесь два списка размещены внутри списка, поэтому на выходе будет список, содержащий списки
С плоской картой => [1,2], [1,1] => [1,2,1,1] Здесь два списка сглаживаются и в список помещаются только значения, поэтому на выходе будет список, содержащий только элементы
В основном это объединяет все объекты в один
Здесь проблема в том, что лямбда, переданная методу карты, возвращает массив String для каждого слова, поэтому поток, возвращаемый методом карты, на самом деле имеет тип Stream, но нам нужен Stream для представления потока символов, ниже изображение иллюстрирует проблема.
Рисунок А:
Вы можете подумать, что мы можем решить эту проблему, используя flatmap,
хорошо, давайте посмотрим, как решить эту проблему, используя map и Arrays.stream. Прежде всего вам понадобится поток символов вместо потока массивов. Существует метод с именем Arrays.stream (), который принимает массив и создает поток, например:
Выше все равно не работает, потому что теперь мы получаем список потоков (точнее, Stream>). Вместо этого мы должны сначала преобразовать каждое слово в массив отдельных букв, а затем превратить каждый массив в отдельный поток.
Используя flatMap, мы сможем решить эту проблему, как показано ниже:
flatMap будет выполнять сопоставление каждого массива не с потоком, а с содержимым этого потока. Все отдельные потоки, которые генерируются при использовании map (Arrays :: stream), объединяются в один поток. На рисунке B показан эффект использования метода flatMap. Сравните это с тем, что делает карта на рисунке A. Рисунок B
Метод flatMap позволяет заменить каждое значение потока другим потоком, а затем объединяет все созданные потоки в один поток.
What’s the difference between map() and flatMap() methods in Java 8?
In Java 8, what’s the difference between Stream.map() and Stream.flatMap() methods?
19 Answers 19
This is reflected in the arguments to each operation.
The flatMap operation takes a function that conceptually wants to consume one value and produce an arbitrary number of values. However, in Java, it’s cumbersome for a method to return an arbitrary number of values, since methods can return only zero or one value. One could imagine an API where the mapper function for flatMap takes a value and returns an array or a List of values, which are then sent to the output. Given that this is the streams library, a particularly apt way to represent an arbitrary number of return values is for the mapper function itself to return a stream! The values from the stream returned by the mapper are drained from the stream and are passed to the output stream. The «clumps» of values returned by each call to the mapper function are not distinguished at all in the output stream, thus the output is said to have been «flattened.»
Typical use is for the mapper function of flatMap to return Stream.empty() if it wants to send zero values, or something like Stream.of(a, b, c) if it wants to return several values. But of course any stream can be returned.
I would like to give 2 examples to get a more practical point of view:
First example making usage of map :
Nothing special in the first example, a Function is applied to return the String in uppercase.
Second example making usage of flatMap :
In the second example, a Stream of List is passed. It is NOT a Stream of Integer!
If a transformation Function has to be used (through map), then first the Stream has to be flattened to something else (a Stream of Integer).
If flatMap is removed then the following error is returned: The operator + is undefined for the argument type(s) List, int.
It is NOT possible to apply + 1 on a List of Integers!
Please go through the post fully to get a clear idea,
map vs flatMap:
To return a length of each word from a list, we would do something like below..
Short Version given below
When we collect two lists, given below
Without flat map => [1,2],[1,1] => [[1,2],[1,1]] Here two lists are placed inside a list, so the output will be list containing lists
With flat map => [1,2],[1,1] => [1,2,1,1] Here two lists are flattened and only the values are placed in list, so the output will be list containing only elements
Basically it merges all the objects in to one
## Detailed Version has been given below:-
For example:-
Consider a list [“STACK”, ”OOOVVVER”] and we are trying to return a list like [“STACKOVER”](returning only unique letters from that list) Initially, we would do something like below to return a list [“STACKOVER”] from [“STACK”, ”OOOVVVER”]
Here the issue is, Lambda passed to the map method returns a String array for each word, So the stream returned by the map method is actually of type Stream, But what we need is Stream to represent a stream of characters, below image illustrates the problem.
Figure A:
You might think that, We can resolve this problem using flatmap,
OK, let us see how to solve this by using map and Arrays.stream First of all you gonna need a stream of characters instead of a stream of arrays. There is a method called Arrays.stream() that would take an array and produces a stream, for example:
The above still does not work, because we now end up with a list of streams (more precisely, Stream>), Instead, we must first convert each word into an array of individual letters and then make each array into a separate stream
By using flatMap we should be able to fix this problem as below:
flatMap would perform mapping each array not with stream but with the contents of that stream. All of the individual streams that would get generated while using map(Arrays::stream) get merged into a single stream. Figure B illustrates the effect of using the flatMap method. Compare it with what map does in figure A. Figure B
The flatMap method lets you replace each value of a stream with another stream and then joins all the generated streams into a single stream.
В чем разница между методами map и flatMap в Java 8?
16 ответов
Это отражается в аргументах каждой операции.
Операция flatMap принимает функцию, которая концептуально хочет потреблять одно значение и производить произвольное количество значений. Однако в Java это громоздко для метода для возврата произвольного количества значений, поскольку методы могут возвращать только ноль или одно значение. Можно представить API, в котором функция mapper для flatMap принимает значение и возвращает массив или List значений, которые затем отправляются на выход. Учитывая, что это библиотека потоков, особенно подходящим способом представления произвольного количества возвращаемых значений является то, что сама функция mapper возвращает поток! Значения из потока, возвращаемого преобразователем, выводятся из потока и передаются в выходной поток. «Сгустки» значений, возвращаемых каждым вызовом функции сопоставления, вообще не различаются в выходном потоке, поэтому выход считается «сплющенным».
Я хотел бы привести 2 примера, чтобы получить более практическую точку зрения:
Первый пример использования карты:
Ничего особенного в первом примере, a Function применяется для возврата String в верхнем регистре.
Второй пример использования flatMap :
Пожалуйста, прочитайте сообщение полностью, чтобы получить четкое представление, map vs flatMap: чтобы вернуть длину каждого слова из списка, мы сделаем что-то вроде ниже..
Например:-
Рассмотрим список [«STACK», «OOOVVVER»], и мы пытаемся вернуть список, например [«STACKOVER»] (возвращая только уникальные буквы из этого списка). Сначала мы сделали бы что-то вроде ниже, чтобы вернуть список [«STACKOVER» ] из [«STACK», «OOOVVVER»]
Здесь проблема заключается в том, что Lambda, переданный методу карты, возвращает массив String для каждого слова. Таким образом, поток, возвращаемый методом карты, фактически имеет тип Stream. Но нам нужно, чтобы Stream представлял поток символов, ниже изображение иллюстрирует проблема.
Рисунок A:
Вы можете подумать, что мы можем решить эту проблему, используя flatmap,
Хорошо, давайте посмотрим, как это решить, используя map и Arrays.stream. Прежде всего вам понадобится поток символов вместо потока массивов. Существует метод под названием Arrays.stream(), который будет принимать массив и создает поток, например:
Вышеизложенное не работает, потому что теперь у нас есть список потоков (точнее, Stream>). Вместо этого мы должны сначала преобразовать каждое слово в массив отдельных букв, а затем сделать каждый массив отдельным потоком
Используя flatMap, мы должны решить эту проблему следующим образом:
flatMap будет выполнять сопоставление каждого массива не с потоком, а с содержимым этого потока. Все отдельные потоки, которые будут генерироваться при использовании карты (Arrays :: stream), объединяются в один поток. Рисунок B иллюстрирует эффект использования метода flatMap. Сравните это с тем, что карта на рисунке A. Рисунок B
Метод flatMap позволяет вам заменить каждое значение потока другим потоком и затем объединить все созданные потоки в один поток.
В чем разница между методами map и flatMap в Java 8?
В Java 8, в чем разница между Stream.map и Stream.flatMap методами?
Это отражено в аргументах каждой операции.
Операция flatMap принимает функцию, которая концептуально хочет использовать одно значение и генерировать произвольное количество значений. Тем не менее, в Java для метода трудно возвращать произвольное количество значений, поскольку методы могут возвращать только ноль или одно значение. Можно представить API, в котором функция mapper для flatMap принимает значение и возвращает массив или List значений, которые затем отправляются на выход. Учитывая, что это библиотека потоков, особенно удачным способом представления произвольного числа возвращаемых значений является то, что сама функция mapper возвращает поток! Значения из потока, возвращаемого преобразователем, выводятся из потока и передаются в выходной поток. «Скопления» значений, возвращаемых при каждом вызове функции преобразования, вообще не различаются в выходном потоке, поэтому говорят, что вывод «сглажен».
Я хотел бы привести 2 примера, чтобы получить более практическую точку зрения:
Первый пример использования карты:
Ничего особенного в первом примере, Function применяется для возврата String в верхнем регистре.
Второй пример использования flatMap :
Во втором примере передается поток списка. Это не поток целых чисел!
Если необходимо использовать функцию преобразования (через карту), то сначала поток должен быть сведен к чему-то другому (поток целых чисел).
Если flatMap удален, возвращается следующая ошибка: Оператор + не определен для типа (ов) аргументов List, int.
Нельзя применять + 1 к списку целых чисел!
Пожалуйста, просмотрите статью полностью, чтобы получить четкое представление,
карта против flatMap:
Чтобы вернуть длину каждого слова из списка, мы бы сделали что-то вроде ниже.
Короткая версия приведена ниже
Когда мы собираем два списка, приведенных ниже
Без плоская карта => [1,2], [1,1] => [[1,2], [1,1]] Здесь два списка размещены внутри списка, поэтому вывод будет список, содержащий списки
с плоской картой => [1,2], [1,1] => [1,2,1,1] Здесь два списка сведены, и в список помещаются только значения, поэтому на выходе будет список, содержащий только элементы
По сути, он объединяет все объекты в один
Здесь проблема в том, что лямбда, переданная методу карты, возвращает массив String для каждого слова, поэтому поток, возвращаемый методом карты, на самом деле имеет тип Stream, но нам нужен Stream для представления потока символов, ниже изображение иллюстрирует проблема.
Рисунок A:
Вы можете подумать, что мы можем решить эту проблему с помощью плоской карты,
Хорошо, давайте посмотрим, как решить эту проблему с помощью map и Arrays.stream Прежде всего, вы собираетесь нужен поток символов вместо потока массивов. Существует метод с именем Arrays.stream (), который принимает массив и создает поток, например:
Выше все равно не работает, потому что теперь мы получаем список потоков (точнее, Stream>). Вместо этого мы должны сначала преобразовать каждое слово Word в массив отдельных букв, а затем сделать каждый массив отдельным потоком.
Используя flatMap, мы сможем решить эту проблему, как показано ниже:
flatMap будет выполнять сопоставление каждого массива не с потоком, а с содержимым этого потока. Все отдельные потоки, которые генерируются при использовании map (Arrays :: stream), объединяются в один поток. На рисунке B показан эффект использования метода flatMap. Сравните это с тем, что делает карта на рисунке A. Рисунок B
Метод flatMap позволяет заменить каждое значение потока другим потоком, а затем объединяет все созданные потоки в один поток.
Как видите, только с map() :
и с flatMap() :
Это результат теста из кода, используемого ниже:
Используемый код :
для карты у нас есть список элементов и (функция, действие) f так:
и для плоской карты у нас есть список элементов списка, и у нас есть (функция, действие) f, и мы хотим, чтобы результат был сведен:
Мы можем избежать использования вложенных списков, используя flatMap :
В статье Oracle, посвященной Optional, подчеркивается это различие между картой и плоской картой:
Итак, чтобы сделать наш код корректным, нам нужно переписать его следующим образом, используя flatMap:
Я не уверен, что должен ответить на этот вопрос, но каждый раз, когда я сталкиваюсь с кем-то, кто этого не понимает, я использую один и тот же пример.
Давайте представим, у меня есть список предметов учеников, где каждый ученик может выбрать несколько предметов.
map () и flatMap ()
Полезно знать, что flapMap () принимает функцию F где
Пример
Примеры Бачири Тауфика см. Ответ здесь просты и легки для понимания. Просто для ясности, скажем так, у нас есть команда разработчиков:
каждый разработчик знает много языков:
Применение Stream.map () к dev_team для получения языков каждого разработчика:
даст вам эту структуру:
поэтому конец вашего кода будет иметь больше смысла, как это:
Когда использовать map () и использовать flatMap () :
Операция flatMap будет производить только Stream чего-либо. EX Stream
Потоковые операции flatMap и map принимают функцию в качестве входных данных.
flatMap ожидает, что функция возвратит новый поток для каждого элемента потока, и возвращает поток, который объединяет все элементы потоков, возвращаемых функцией для каждого элемента. Другими словами, с flatMap для каждого элемента из источника, функция будет создавать несколько элементов. http://www.zoftino.com/Java-stream-examples#flatmap-operation
map ожидает, что функция вернет преобразованное значение и вернет новый поток, содержащий преобразованные элементы. Другими словами, с map для каждого элемента из источника функция создаст один преобразованный элемент. http://www.zoftino.com/Java-stream-examples#map-operation
flatMap() также использует частичную ленивую оценку потоков. Он будет читать первый поток и только при необходимости перейдет к следующему потоку. Поведение подробно объясняется здесь: Гарантируется, что flatMap будет ленивым?