Java 8 Stream y operación en matrices


197

Acabo de descubrir las nuevas capacidades de transmisión de Java 8. Viniendo de Python, me preguntaba si ahora había una forma ordenada de hacer operaciones en matrices como sumar, multiplicando dos matrices en una forma "pitónica de una línea".

Gracias

Respuestas:


294

Se han agregado nuevos métodos java.util.Arrayspara convertir una matriz en una secuencia Java 8 que luego se puede usar para sumar, etc.

int sum =  Arrays.stream(myIntArray)
                 .sum();

Multiplicar dos matrices es un poco más difícil porque no puedo pensar en una forma de obtener el valor Y el índice al mismo tiempo que una operación Stream. Esto significa que probablemente tenga que transmitir sobre los índices de la matriz.

//in this example a[] and b[] are same length
int[] a = ...
int[] b = ...

int[] result = new int[a.length];

IntStream.range(0, a.length)
         .forEach(i -> result[i] = a[i] * b[i]);

EDITAR

El comentarista @Holger señala que puede usar el mapmétodo en lugar de hacerlo forEachasí:

int[] result = IntStream.range(0, a.length).map(i -> a[i] * b[i]).toArray();

13
int[] result=IntStream.range(0, a.length).map( i->a[i]* b[i]).toArray();
Holger

2
@ Holger sí, eso también funcionaría. Aunque probablemente quieras usar mapToIntpara evitar el boxeo.
dkatzel

Eso último equivale a una simulación de zip donde debe preasignar almacenamiento para el resultado. Me pregunto por qué no hay zip en la biblioteca Streams.
Reb.Cabin

De acuerdo con esta respuesta SO , un zip estaba en una versión beta anterior de Java 8 y luego se eliminó. Afortunadamente, el cartel tenía la fuente y está en la respuesta. He usado el código varias veces y parece funcionar muy bien.
sparc_spread

@dkatzel: dado que ya es un IntStream, "map" toma un IntUnaryOperator, por lo que no hay boxeo involucrado.
M. Justin

58

Puede convertir una matriz en una secuencia utilizando Arrays.stream():

int[] ns = new int[] {1,2,3,4,5};
Arrays.stream(ns);

Una vez que tenga su transmisión, puede usar cualquiera de los métodos descritos en la documentación , como sum()o lo que sea. Puede mapo le filtergusta en Python llamando a los métodos de transmisión relevantes con una función Lambda:

Arrays.stream(ns).map(n -> n * 2);
Arrays.stream(ns).filter(n -> n % 4 == 0);

Una vez que haya terminado de modificar su transmisión, llame toArray()para convertirla nuevamente en una matriz para usar en otro lugar:

int[] ns = new int[] {1,2,3,4,5};
int[] ms = Arrays.stream(ns).map(n -> n * 2).filter(n -> n % 4 == 0).toArray();

9

Tenga cuidado si tiene que lidiar con grandes números.

int[] arr = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE};
long sum = Arrays.stream(arr).sum(); // Wrong: sum == 0

La suma anterior no es 2 * Integer.MIN_VALUE. Necesitas hacer esto en este caso.

long sum = Arrays.stream(arr).mapToLong(Long::valueOf).sum(); // Correct

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.