Java 8 Stream i działanie na tablicach

197

Właśnie odkryłem nowe możliwości strumienia Java 8. Pochodząc z Pythona, zastanawiałem się, czy istnieje teraz dobry sposób na wykonywanie operacji na tablicach, takich jak sumowanie, mnożenie dwóch tablic w sposób „pythonowy” w jednej linii?

Dzięki

BlackLabrador
źródło

Odpowiedzi:

294

Dodano nowe metody java.util.Arrayskonwertowania tablicy na strumień Java 8, który można następnie wykorzystać do sumowania itp.

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

Mnożenie dwóch tablic jest nieco trudniejsze, ponieważ nie mogę wymyślić sposobu na uzyskanie wartości ORAZ indeksu jednocześnie z operacją Stream. Oznacza to, że prawdopodobnie musisz przesyłać strumieniowo przez indeksy tablicy.

//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]);

EDYTOWAĆ

Commenter @Holger wskazuje, można użyć mapmetody zamiast forEachtak:

int[] result = IntStream.range(0, a.length).map(i -> a[i] * b[i]).toArray();
dkatzel
źródło
13
int[] result=IntStream.range(0, a.length).map( i->a[i]* b[i]).toArray();
Holger
2
@ Holger tak, to też by działało. Chociaż prawdopodobnie chcesz użyć, mapToIntaby uniknąć boksu.
dkatzel
To ostatnie oznacza symulację zip, w której musisz wstępnie przydzielić miejsce na wynik. Zastanawiam się, dlaczego nie ma zip w bibliotece Streams?
Reb.Cabin
Zgodnie z tą odpowiedzią SO , zip był we wcześniejszej wersji beta Java 8, a następnie wyjęty. Na szczęście plakat miał źródło i jest w odpowiedzi. Użyłem kodu kilka razy i wydaje się, że działa bardzo dobrze.
sparc_spread
@dkatzel - Ponieważ jest to już IntStream, „mapa” zajmuje IntUnaryOperator, więc nie jest wymagane żadne boksowanie.
M. Justin,
58

Możesz zmienić tablicę w strumień, używając Arrays.stream():

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

Po otrzymaniu strumienia możesz użyć dowolnej z metod opisanych w dokumentacji , takich jak sum()cokolwiek. Można mapalbo filterjak w Pythonie poprzez wywołanie odpowiednich metod strumieniowych z funkcji Lambda:

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

Po zakończeniu modyfikowania strumienia wywołujesz go, toArray()aby przekonwertować go z powrotem na tablicę i użyć w innym miejscu:

int[] ns = new int[] {1,2,3,4,5};
int[] ms = Arrays.stream(ns).map(n -> n * 2).filter(n -> n % 4 == 0).toArray();
Ian Knight
źródło
9

Uważaj, jeśli masz do czynienia z dużymi liczbami.

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

Powyższa suma nie jest 2 * Integer.MIN_VALUE. W tym przypadku musisz to zrobić.

long sum = Arrays.stream(arr).mapToLong(Long::valueOf).sum(); // Correct
Sanghyun Lee
źródło