print - stream operations in java 8 can be divided into
Diferencia de Java Stream entre map y mapToObj (2)
No siento la diferencia entre map()
métodos map()
y mapToObj()
en Java 8 Streams. En ambos podemos crear y devolver objetos a los flujos, por lo que estos métodos existen como dos, no solo uno.
¿Podrías darme la explicación con ejemplos?
Las versiones primitive
y de object
de los tipos de datos (es decir, int y Integer, double y Double, etc.) no son realmente compatibles entre sí en Java. Se hacen compatibles a través del paso adicional de auto-boxing/unboxing
. Por lo tanto, si tiene un flujo de entradas primitivas y si intenta usar las versiones de objeto de Secuencia y función (es decir, Secuencia y función), incurrirá en el costo de boxear y desempaquetar los elementos.
Para eliminar este problema, el paquete de funciones contiene primitive specialized versions of streams
, así como functional interfaces
. Por ejemplo, en lugar de usar Stream<Integer>
, debe usar IntStream
. Ahora puede procesar cada elemento de la secuencia utilizando IntFunction. Esto evitará el auto-boxing / unboxing por completo.
Por lo tanto, cuando quiera procesar flujos de elementos primitivos, debe usar los flujos especializados primitivos (es decir, IntStream, LongStream y DoubleStream) y las interfaces funcionales especializadas primitivas (es decir, IntFunction, IntConsumer, IntSupplier, etc.) para lograr un mejor rendimiento.
Una cosa más a tener en cuenta es que ninguna de las interfaces funcionales especializadas primitivas (como IntFunction, DoubleFunction o IntConsumer) extienden las interfaces funcionales no primitivas (es decir, Función, Consumidor, etc.).
java.util.function package
contiene versiones int, dobles y largas (pero no flotantes) de todas las interfaces funcionales. Por ejemplo, hay una IntFunction, una DoubleFunction y una LongFunction, que son versiones int, double y long de la función. Estas funciones se utilizan junto con versiones primitivas especializadas de secuencias como IntStream, DoubleStream y LongStream.
Tomemos algunos ejemplos:
Stream stream = Stream.of(1, 2, 3); //Will compile fine
IntStream intStream = IntStream.of(4, 5, 6); //Will compile fine
Stream s = IntStream.of(4, 5, 6); //Does not compile
Stream s = IntStream.of(4, 5, 6).mapToObj(e -> e); //mapToObj method is needed
IntStream is = Stream.of(4, 5, 6).mapToInt(e -> e); //mapToInt method is needed
Como conclusión, la razón por la que puede usar mapToObj
es la misma que puede usar mapToInt
, que es para cambiar el tipo de flujo.
Verás este patrón fresco. Las clases de IntStream
incluyen un IntStream
, LongStream
, DoubleStream
, etc. Esto es para que pueda usar tipos primitivos en las operaciones de transmisión. Porque de lo contrario tienes que usar Stream<Integer>
o Stream<Double>
, que encajará los valores.
Del mismo modo, los métodos de map
también hacen esto. En la clase Stream<T>
, hay métodos mapToInt
, mapToDouble
, pero la situación es un poco diferente en las clases IntStream
, DoubleStream
.
En IntStream
, el método de map
toma un IntUnaryOperator
, que asigna un int a un int. Si desea asignar el flujo a un Stream<T>
, debe usar mapToObj
. mapToObj
es un buen nombre porque se distingue del map
que se asigna a ints. Significa que la transmisión cambia de un IntStream
a una IntStream
Stream<T>
. La razón por la que mapToObj
se llama así es la misma razón por la que mapToInt
se llama así: para indicar un cambio en el tipo de Stream
/