Pengantar Java Threads di Java 8
Java Streams, diperkenalkan sebagai bagian dari Java 8, digunakan untuk bekerja dengan kumpulan data. Mereka bukan merupakan struktur data itu sendiri, namun dapat digunakan untuk memasukkan informasi dari struktur data lain dengan mengurutkan dan menyalurkan untuk menghasilkan hasil akhir. Catatan: Penting untuk tidak membingungkan Stream dan Thread, karena dalam bahasa Rusia kedua istilah tersebut sering disebut dalam terjemahan yang sama “aliran”. Stream menunjukkan objek untuk melakukan operasi (paling sering mentransfer atau menyimpan data), sedangkan Thread (terjemahan literal - thread) menunjukkan objek yang memungkinkan kode program tertentu dieksekusi secara paralel dengan cabang kode lainnya. Karena Stream bukan struktur data terpisah, Stream tidak pernah mengubah sumber data. Aliran Java memiliki beberapa fitur berikut:-
Java Stream dapat digunakan menggunakan paket “java.util.stream”. Itu dapat diimpor ke skrip menggunakan kode:
import java.util.stream.* ;
Dengan menggunakan kode ini, kita juga dapat dengan mudah mengimplementasikan beberapa fungsi bawaan di Java Stream.
-
Java Stream dapat menerima masukan dari kumpulan data seperti koleksi dan array di Java.
-
Java Stream tidak memerlukan perubahan struktur data masukan.
-
Java Stream tidak mengubah sumbernya. Sebaliknya, ini menghasilkan keluaran menggunakan metode saluran pipa yang sesuai.
-
Java Streams tunduk pada operasi perantara dan terminal, yang akan kita bahas di bagian berikut.
-
Di Java Stream, operasi perantara disalurkan dan terjadi dalam format evaluasi yang lambat. Mereka diakhiri dengan fungsi terminal. Ini membentuk format dasar untuk menggunakan Java Stream.
Membuat Aliran Java di Java 8
Thread Java dapat dibuat dengan beberapa cara:1. Membuat aliran kosong menggunakan metode Stream.empty()
Anda dapat membuat aliran kosong untuk digunakan nanti dalam kode Anda. Jika Anda menggunakan metode Stream.empty() , aliran kosong akan dihasilkan, tidak berisi nilai. Aliran kosong ini bisa berguna jika kita ingin melewatkan pengecualian penunjuk nol saat runtime. Untuk melakukan ini, Anda dapat menggunakan perintah berikut:Stream<String> str = Stream.empty();
Pernyataan di atas akan menghasilkan aliran kosong bernama str tanpa elemen apa pun di dalamnya. Untuk memverifikasi ini, cukup periksa jumlah atau ukuran aliran menggunakan istilah str.count() . Misalnya,
System.out.println(str.count());
Hasilnya, kita mendapatkan 0 pada output .
2. Buat aliran menggunakan metode Stream.builder() dengan instance Stream.Builder
Kita juga dapat menggunakan Stream Builder untuk membuat aliran menggunakan pola desain pembuat. Ini dirancang untuk konstruksi objek selangkah demi selangkah. Mari kita lihat bagaimana kita dapat membuat instance aliran menggunakan Stream Builder .Stream.Builder<Integer> numBuilder = Stream.builder();
numBuilder.add(1).add(2).add( 3);
Stream<Integer> numStream = numBuilder.build();
Dengan menggunakan kode ini, Anda dapat membuat aliran bernama numStream yang berisi elemen int . Semuanya dilakukan cukup cepat berkat instance Stream.Builder bernama numBuilder yang dibuat terlebih dahulu.
3. Buat aliran dengan nilai yang ditentukan menggunakan metode Stream.of()
Cara lain untuk membuat aliran melibatkan penggunaan metode Stream.of() . Ini adalah cara sederhana untuk membuat aliran dengan nilai tertentu. Ini mendeklarasikan dan juga menginisialisasi thread. Contoh penggunaan metode Stream.of() untuk membuat aliran:Stream<Integer> numStream = Stream.of(1, 2, 3);
Kode ini akan membuat aliran yang berisi elemen int , seperti yang kita lakukan pada metode sebelumnya menggunakan Stream.Builder . Di sini kita langsung membuat aliran menggunakan Stream.of() dengan nilai yang telah ditentukan sebelumnya [1, 2 dan 3] .
4. Buat aliran dari array yang ada menggunakan metode Arrays.stream()
Metode umum lainnya untuk membuat thread melibatkan penggunaan array di Java. Aliran di sini dibuat dari array yang ada menggunakan metode Arrays.stream() . Semua elemen array diubah menjadi elemen aliran. Berikut ini contoh yang bagus:Integer[] arr = {1, 2, 3, 4, 5};
Stream<Integer> numStream = Arrays.stream(arr);
Kode ini akan menghasilkan numStream yang berisi konten array bernama arr, yang merupakan array integer.
5. Menggabungkan dua aliran yang ada menggunakan metode Stream.concat()
Metode lain yang dapat digunakan untuk membuat aliran adalah metode Stream.concat() . Ini digunakan untuk menggabungkan dua utas untuk membuat satu utas. Kedua aliran digabungkan secara berurutan. Artinya thread pertama didahulukan, disusul thread kedua, dan seterusnya. Contoh penggabungannya terlihat seperti ini:Stream<Integer> numStream1 = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> numStream2 = Stream.of(1, 2, 3);
Stream<Integer> combinedStream = Stream.concat( numStream1, numStream2);
Pernyataan di atas akan membuat aliran akhir bernama gabunganStream yang berisi elemen aliran pertama numStream1 dan aliran kedua numStream2 satu per satu .
Jenis operasi dengan Java Stream
Seperti yang telah disebutkan, Anda dapat melakukan dua jenis operasi dengan Java Stream di Java 8: perantara dan terminal. Mari kita lihat masing-masing secara lebih rinci.Operasi perantara
Operasi perantara menghasilkan aliran keluaran dan dijalankan hanya ketika menghadapi operasi terminal. Ini berarti bahwa operasi perantara dijalankan dengan lambat, tersalurkan, dan hanya dapat diselesaikan oleh operasi terminal. Anda akan belajar tentang evaluasi malas dan pipeline nanti. Contoh operasi perantara adalah metode berikut: filter() , map() , differential() , peek() , sortir() dan beberapa lainnya.Operasi Terminal
Operasi terminal menyelesaikan pelaksanaan operasi perantara dan juga mengembalikan hasil akhir dari aliran keluaran. Karena operasi terminal menandakan berakhirnya eksekusi lambat dan pipeline, thread ini tidak dapat digunakan lagi setelah menjalani operasi terminal. Contoh operasi terminal adalah metode berikut: forEach() , Collect() , count() , Reduce() dan seterusnya.Contoh operasi dengan Java Stream
Operasi perantara
Berikut adalah beberapa contoh beberapa operasi perantara yang dapat diterapkan pada Java Stream:Saring()
Metode ini digunakan untuk memfilter elemen dari aliran yang cocok dengan predikat tertentu di Java. Item yang difilter ini kemudian membentuk aliran baru. Mari kita lihat contoh untuk lebih memahaminya.Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); List<Integer> even = numStream.filter(n -> n % 2 == 0) .collect(Collectors.toList()); System.out.println(even);
Kesimpulan:
peta()
Metode ini digunakan untuk membuat aliran baru dengan menjalankan fungsi yang dipetakan pada elemen aliran masukan asli. Mungkin aliran baru memiliki tipe data yang berbeda. Contohnya terlihat seperti ini:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); List<Integer> d = numStream.map(n -> n*2) .collect(Collectors.toList()); System.out.println(d);
Kesimpulan:
berbeda()
Metode ini digunakan untuk mengambil hanya elemen individual dalam aliran dengan memfilter duplikat. Contohnya terlihat seperti ini:Stream<Integer> numStream = Stream.of(43,65,1,98,63,63,1); List<Integer> numList = numStream.distinct() .collect(Collectors.toList()); System.out.println(numList);
Kesimpulan:
mengintip()
Metode ini digunakan untuk melacak perubahan antara sebelum menjalankan operasi terminal. Ini berarti peek() dapat digunakan untuk melakukan operasi pada setiap elemen aliran untuk membuat aliran di mana operasi perantara lebih lanjut dapat dilakukan.Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); List<Integer> nList = numStream.map(n -> n*10) .peek(n->System.out.println("Mapped: "+ n)) .collect(Collectors.toList()); System.out.println(nList);
Kesimpulan:
diurutkan()
Metode sortir() digunakan untuk mengurutkan elemen aliran. Secara default, ini mengurutkan elemen dalam urutan menaik. Anda juga dapat menentukan urutan tertentu sebagai parameter. Contoh penerapan metode ini terlihat seperti ini:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); numStream.sorted().forEach(n -> System.out.println(n));
Kesimpulan:
Operasi Terminal
Berikut beberapa contoh beberapa operasi terminal yang dapat diterapkan pada aliran Java:untuk setiap()
Metode forEach() digunakan untuk mengulangi semua elemen aliran dan menjalankan fungsi pada setiap elemen satu per satu. Ini bertindak sebagai alternatif untuk pernyataan loop seperti for , while dan lain-lain. Contoh:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); numStream.forEach(n -> System.out.println(n));
Kesimpulan:
menghitung()
Metode count() digunakan untuk mengambil jumlah total elemen yang ada di aliran. Ini mirip dengan metode size() , yang sering digunakan untuk menentukan jumlah total elemen dalam suatu koleksi. Contoh penggunaan metode count() dengan Java Stream adalah sebagai berikut:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); System.out.println(numStream.count());
Kesimpulan:
mengumpulkan()
Metode Collect() digunakan untuk melakukan reduksi elemen aliran yang dapat diubah. Ini dapat digunakan untuk menghapus konten dari aliran setelah pemrosesan selesai. Ia menggunakan kelas Collector untuk melakukan reduksi .Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); List<Integer> odd = numStream.filter(n -> n % 2 == 1) .collect(Collectors.toList()); System.out.println(odd);
Kesimpulan:
min() dan maks()
Metode min() , seperti namanya, dapat digunakan pada aliran untuk menemukan elemen minimum di dalamnya. Demikian pula, metode max() dapat digunakan untuk menemukan elemen maksimum dalam suatu aliran. Mari kita coba memahami bagaimana mereka dapat digunakan dengan sebuah contoh:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); int smallest = numStream.min((m, n) -> Integer.compare(m, n)).get(); System.out.println("Smallest element: " + smallest);
numStream = Stream.of(43, 65, 1, 98, 63); int largest = numStream.max((m, n) -> Integer.compare(m, n)).get(); System.out.println("Largest element: " + largest);
Kesimpulan:
findAny() dan findFirst()
findAny() mengembalikan elemen aliran apa pun sebagai Optional . Jika alirannya kosong, ia juga akan mengembalikan Optional value , yang akan kosong. findFirst() mengembalikan elemen pertama aliran sebagai Opsional . Seperti halnya metode findAny() , metode findFirst() juga mengembalikan parameter Opsional kosong jika aliran terkait kosong. Mari kita lihat contoh berikut berdasarkan metode ini:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); Optional<Integer> opt = numStream.findFirst();System.out.println(opt); numStream = Stream.empty(); opt = numStream.findAny();System.out.println(opt);
Kesimpulan:
allMatch() , anyMatch() dan noneMatch()
Metode allMatch() digunakan untuk memeriksa apakah semua elemen dalam aliran cocok dengan predikat tertentu dan mengembalikan nilai boolean true jika cocok, jika tidak maka akan mengembalikan false . Jika alirannya kosong, ia mengembalikan true . Metode anyMatch() digunakan untuk memeriksa apakah salah satu elemen dalam aliran cocok dengan predikat tertentu. Ia mengembalikan nilai benar jika demikian, salah jika sebaliknya. Jika alirannya kosong, ia mengembalikan false . Metode noneMatch() mengembalikan nilai true jika tidak ada elemen dalam aliran yang cocok dengan predikatnya, dan false jika tidak. Contoh untuk mengilustrasikannya terlihat seperti ini:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); boolean flag = numStream.allMatch(n -> n1); System.out.println(flag); numStream = Stream.of(43, 65, 1, 98, 63); flag = numStream.anyMatch(n -> n1); System.out.println(flag); numStream = Stream.of(43, 65, 1, 98, 63); flag = numStream.noneMatch(n -> n==1);System.out.println(flag);
Kesimpulan:
Evaluasi Malas di Java Stream
Evaluasi yang lambat mengarah pada pengoptimalan saat bekerja dengan Java Streams di Java 8. Evaluasi ini terutama melibatkan penundaan operasi perantara hingga operasi terminal ditemukan. Evaluasi yang malas bertanggung jawab untuk mencegah pemborosan sumber daya yang tidak perlu dalam perhitungan hingga hasilnya benar-benar dibutuhkan. Aliran keluaran yang dihasilkan dari operasi perantara dihasilkan hanya setelah operasi terminal selesai. Evaluasi malas berfungsi dengan semua operasi perantara di aliran Java. Penggunaan evaluasi malas yang sangat berguna terjadi ketika bekerja dengan aliran tak terbatas. Dengan cara ini, banyak pemrosesan yang tidak perlu dapat dicegah.Saluran pipa di Java Stream
Sebuah pipeline di Java Stream terdiri dari aliran input, nol atau lebih operasi perantara yang berbaris satu demi satu, dan terakhir operasi terminal. Operasi perantara di Java Streams dilakukan dengan lambat. Hal ini membuat operasi perantara melalui pipa tidak dapat dihindari. Dengan pipeline, yang pada dasarnya merupakan operasi perantara yang digabungkan secara berurutan, eksekusi yang lambat menjadi mungkin. Saluran pipa membantu melacak operasi perantara yang perlu dilakukan setelah operasi terminal akhirnya ditemui.Kesimpulan
Mari kita rangkum apa yang telah kita pelajari hari ini. Dalam artikel ini:- Kami melihat sekilas apa itu Java Streams.
- Kami kemudian mempelajari banyak teknik berbeda untuk membuat thread Java di Java 8.
- Kita mempelajari dua jenis operasi utama (operasi perantara dan operasi terminal) yang dapat dilakukan pada aliran Java.
- Kami kemudian melihat secara rinci beberapa contoh operasi perantara dan terminal.
- Kami akhirnya belajar lebih banyak tentang evaluasi malas dan akhirnya belajar tentang pipelining di thread Java.
GO TO FULL VERSION