Haruskah mengubah Traditional Loop ke Java Stream API ?

Lambang Prabawa
Javan Cipta Solusi

--

Stream merupakan salah satu fitur yang terdapat di Java 8, Stream yang akan saya bahas disini berbeda dengan Stream dari Java I/O, melainkan stream yang yang terdapat pada package java.util.stream. Sebelum melanjutkan pembahasan, untuk penjelasan lebih jauh tentang Stream anda dapat mengunjungi link ini.

“Stream represents a sequence of objects from a source, which supports aggregate operations”

Berdasarkan referensi yang saya baca, fungsi Stream dapat menggantikan fungsi Traditional Loop yang biasa digunakan pada java, dari beberapa artikel yang saya temukan tentang penggunaan stream terdapat masalah di sisi performa di mana stream 5x lebih lambat di bandingkan dengan Traditional Loop, nah di sini saya akan mencoba sendiri melakukan Simple Benchmark untuk membandingkan apakah benar Stream lebih lambat di bandingkan Traditional Loop dan dari sisi kemudahan bagi developer apakah Stream lebih baik di bandingkan dengan Traditional Loop yang lebih umum digunakan?

Dari sisi kemudahan, berdasarkan beberapa kasus yang saya temukan, stream tidak berbeda jauh di bandingkan Traditional Loop, mungkin saya belum explore lebih jauh lagi mengenai Stream ini :D, tetapi yang sangat saya rasakan dalam penulisan kode Stream lebih simple di bandingkan Traditional Loop dan lebih bergaya ke functional programming , contoh nya seperti kasus di bawah :

A. Kasus 1

  • Traditional Loop (For Each)
long jmlEvaluasiDitolak = 0;

for (Evaluasi evaluasi : evaluasiList){

if (evaluasi.eva_status == Evaluasi.StatusEvaluasi.DITOLAK)
jmlEvaluasiDitolak++;

}
  • Stream
long jmlEvaluasiDitolak = evaluasiList.stream()
.filter(e -> (e.eva_status == Evaluasi.StatusEvaluasi.DITOLAK))
.count();

B. Kasus 2

  • Collections.Sort + Traditional Loop (For Each)
List<Rekanan> sortedRekananList = new ArrayList<>();

Collections.sort(pesertaList, new Comparator<Peserta>() {

@Override
public Double compare(Peserta p1, Peserta p2) {
return p2.psr_harga.compareTo(p1.psr_harga);
}
});

for(Peserta peserta : pesertaList){

sortedRekananList.add(peserta.getRekanan());

}
  • Stream
List<Rekanan> sortedRekananList = pesertaList.stream()
.sorted((e1, e2) -> Double.compare(e2.psr_harga, e1.psr_harga))
.map(e -> e.getRekanan())
.collect(Collectors.toList());

Selanjut nya saya akan coba melakukan Simple Benchmark untuk membandingkan dari segi performance, metode yang saya gunakan yaitu dengan melakukan assignment System.nanoTime()ke dua variabel, yang akan di tempatkan di awal dan akhir baris pada kode yang akan di uji, lalu dengan melakukan pengurangan dari ke dua variable tersebut bisa didapat jumlah waktu pengeksekusian kode yang di uji, untuk lebih detail nya bisa lihat di bawah :

long start = System.nanoTime();


//block kode yang akan di uji


long end = System.nanoTime();

System.out.println("Hasil 1: "+(double)(end - start) / 1000000+" ms");

Di bawah ini saya menjabarkan hasil dari pengujian Stream dan Traditional Loop, dengan menyertakan kode yang di uji dan juga hasil waktu eksekusi nya.

*Note : Hasil 1 = Traditional Loop, Hasil 2 = Stream

A. For

  • Traditional
for(int f = 0; f < 200; f++){

System.out.println();

}
  • Stream
IntStream.range(0, 200).forEach(e -> System.out.println());

Result :

  • Traditional
for(int f = 0; f < 200; f++){

for (int g = 0; g < 300; g++){

if ((g % 2) == 0)
System.out.println(g);

}

}
  • Stream
IntStream.range(0, 200)
.forEach(e -> {IntStream.range(0,300).filter(x -> (x % 2) == 0)
.forEach(x->System.out.println(x));
});

Result :

B. For Each

  • Traditional
for(HasilEvaluasi hasilEvaluasi : hasilEvaluasiList){

System.out.println(">>> "+hasilEvaluasi.psr_alasan_menang);

}
  • Stream
hasilEvaluasiList.stream()
.forEach(e -> System.out.println(e.psr_alasan_menang));

Result :

  • Traditional
for(HasilEvaluasi hasilEvaluasi : hasilEvaluasiList){

if (hasilEvaluasi.isLulusPembuktian())
collectEvaluasiList.add(hasilEvaluasi);

}
  • Stream
collectEvaluasiList = hasilEvaluasiList.stream()
.filter(e->e.isLulusPembuktian())
.collect(Collectors.toList());

Result :

  • Traditional
for(Panitia panitia : panitiaList){

for (Anggota_panitia anggota_panitia : panitia.getAnggota_panitiaList()) {

System.out.println(">>> " + anggota_panitia.isKetua());

}

}
  • Stream
panitiaList.stream()
.forEach(e->{e.getAnggota_panitiaList().stream()
.forEach(x->System.out.println(">>> "+x.isKetua()));
});

Result :

Berdasarkan hasil pengujian yang saya sendiri lakukan Stream lebih cepat di bandingkan Traditional Loop dalam pengeksekusian kode walaupun perbedaan waktu nya tidak terlalu signifikan. Sangat berbeda hasil nya dengan artikel-artikel di luar sana yang menujukan hasil pengujian Stream lebih lambat di bandingkan Traditional Loop, perlu di ingat bahwa system dan hardware yang di gunakan sangat berpengaruh terhadap hasil dari pengujian, dan juga versi JDK yang saya gunakan mungkin saja versi yang sudah di lakukan perbaikan masalah performance pada Stream ini.

Jadi untuk kesimpulannya, haruskah mengubah Traditional Loop ke Java Stream API ? berdasarkan hasil pengujian, walaupun hanya melakukan Simple Benchmark dan dari beberapa kasus yang saya temukan Stream layak untuk menggantikan Traditional Loop yang sudah umum di gunakan. Atau anda bisa melakukan pengujian sendiri, sehingga dapat memberikan kesimpulan yang berbeda dengan saya.

Sumber :

https://dzone.com/articles/dipping-into-java-8-streams

--

--