Java 8 Stream e operação em matrizes


197

Acabei de descobrir os novos recursos de fluxo do Java 8. Vindo de Python, eu queria saber se havia agora uma maneira elegante de fazer operações em matrizes como soma, multiplicando duas matrizes de uma maneira "uma linha pitônica"?

obrigado

Respostas:


294

Foram adicionados novos métodos java.util.Arrayspara converter uma matriz em um fluxo Java 8 que pode ser usado para somar, etc.

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

Multiplicar duas matrizes é um pouco mais difícil, porque não consigo pensar em uma maneira de obter o valor E o índice ao mesmo tempo que uma operação de Stream. Isso significa que você provavelmente precisará transmitir sobre os índices da 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

O Commenter @Holger indica que você pode usar o mapmétodo em vez de forEach:

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 sim, isso também funcionaria. Embora você provavelmente queira usar mapToIntpara evitar o boxe.
dkatzel

Essa última equivale a uma simulação de zip, na qual você deve pré-alocar o armazenamento para o resultado. Gostaria de saber por que não há zip na biblioteca do Streams?
Reb.Cabin

De acordo com essa resposta do SO , um zip estava em uma versão beta anterior do Java 8 e depois retirado. Felizmente, o pôster tinha a fonte e está na resposta. Eu usei o código várias vezes e parece funcionar muito bem.
Sparc_spread

@dkatzel - Como já é um IntStream, "map" usa um IntUnaryOperator, portanto não há boxe envolvido.
237 Justin

58

Você pode transformar uma matriz em um fluxo usando Arrays.stream():

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

Depois de obter seu fluxo, você pode usar qualquer um dos métodos descritos na documentação , como sum()ou o que quer. Você pode gostar mapou filtergostar do Python chamando os métodos de fluxo relevantes com uma função Lambda:

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

Depois de modificar o seu fluxo, chame-o toArray()para convertê-lo novamente em uma matriz para usar em outro 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

Tenha cuidado se você tiver que lidar com grandes números.

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

A soma acima não é 2 * Integer.MIN_VALUE. Você precisa fazer isso neste caso.

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.