Java 8 Streaming dan operasi pada array

197

Saya baru saja menemukan kemampuan Java 8 stream yang baru. Berasal dari Python, saya bertanya-tanya apakah sekarang ada cara yang rapi untuk melakukan operasi pada array seperti menjumlahkan, mengalikan dua array dalam cara "satu baris pythonic"?

Terima kasih

BlackLabrador
sumber

Jawaban:

294

Ada metode baru yang ditambahkan untuk java.util.Arraysmengubah array menjadi aliran Java 8 yang kemudian dapat digunakan untuk menjumlahkan dll.

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

Mengalikan dua array sedikit lebih sulit karena saya tidak bisa memikirkan cara untuk mendapatkan nilai DAN indeks pada saat yang sama dengan operasi Stream. Ini berarti Anda mungkin harus melakukan streaming indeks array.

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

EDIT

Commenter @Holger menunjukkan Anda dapat menggunakan mapmetode bukan forEachseperti ini:

int[] result = IntStream.range(0, a.length).map(i -> a[i] * b[i]).toArray();
dkatzel
sumber
13
int[] result=IntStream.range(0, a.length).map( i->a[i]* b[i]).toArray();
Holger
2
@ Holger ya itu akan berhasil juga. Meskipun Anda mungkin ingin menggunakan mapToIntuntuk menghindari tinju.
dkatzel
Yang terakhir merupakan simulasi zip di mana Anda harus melakukan pra-alokasi penyimpanan untuk hasilnya. Saya bertanya-tanya mengapa tidak ada zip di perpustakaan Streams?
Reb.Cabin
Menurut jawaban SO ini , sebuah zip ada di beta Java 8 yang lebih awal, kemudian dikeluarkan. Untungnya poster itu memiliki sumber dan jawabannya ada. Saya telah menggunakan kode beberapa kali dan sepertinya berfungsi dengan sangat baik.
sparc_spread
@dkatzel - Karena sudah menjadi IntStream, "peta" menggunakan IntUnaryOperator, jadi tidak ada tinju yang terlibat.
M. Justin
58

Anda dapat mengubah array menjadi aliran dengan menggunakan Arrays.stream():

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

Setelah Anda mendapatkan aliran Anda, Anda dapat menggunakan salah satu metode yang dijelaskan dalam dokumentasi , seperti sum()atau apa pun. Anda bisa mapatau filtersuka dengan Python dengan memanggil metode stream yang relevan dengan fungsi Lambda:

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

Setelah selesai memodifikasi aliran Anda, Anda kemudian menelepon toArray()untuk mengubahnya kembali menjadi array untuk digunakan di tempat lain:

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
sumber
9

Hati-hati jika harus berhadapan dengan jumlah besar.

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

Jumlah di atas tidak 2 * Integer.MIN_VALUE. Anda perlu melakukan ini dalam hal ini.

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

Harap perhatikan bahwa Arrays.stream (arr) membuat LongStream (atau IntStream, ...) alih-alih Stream sehingga fungsi peta tidak dapat digunakan untuk memodifikasi tipe. Inilah mengapa fungsi .mapToLong, mapToObject, ... disediakan.

Lihatlah mengapa-cant-i-map-integers-to-string-saat-streaming-dari-an-array

Rafael
sumber