Pengantar Java Fungsional

1. Ikhtisar

Dalam tutorial ini, kami akan memberikan gambaran umum singkat tentang perpustakaan Java Fungsional bersama dengan beberapa contoh.

2. Perpustakaan Java Fungsional

Pustaka Java Fungsional adalah pustaka sumber terbuka yang dimaksudkan untuk memfasilitasi pemrograman fungsional di Java. Perpustakaan menyediakan banyak abstraksi pemrograman dasar dan lanjutan yang biasa digunakan dalam Pemrograman Fungsional.

Sebagian besar fungsionalitas perpustakaan berputar di sekitar antarmuka F. Ini F model antarmuka fungsi yang mengambil input tipe A dan mengembalikan output tipe B . Semua ini dibangun di atas sistem tipe Java sendiri.

3. Ketergantungan Maven

Pertama, kita perlu menambahkan dependensi yang diperlukan ke file pom.xml kita :

 org.functionaljava functionaljava 4.8.1   org.functionaljava functionaljava-java8 4.8.1   org.functionaljava functionaljava-quickcheck 4.8.1   org.functionaljava functionaljava-java-core 4.8.1 

4. Mendefinisikan Fungsi

Mari kita mulai dengan membuat fungsi yang bisa kita gunakan dalam contoh kita nanti.

Tanpa Java Fungsional, metode perkalian dasar akan terlihat seperti:

public static final Integer timesTwoRegular(Integer i) { return i * 2; }

Dengan menggunakan pustaka Java Fungsional, kita dapat mendefinisikan fungsionalitas ini dengan lebih elegan:

public static final F timesTwo = i -> i * 2;

Di atas, kita melihat contoh antarmuka F yang mengambil Integer sebagai input dan mengembalikan Integer dikalikan dua sebagai outputnya.

Berikut adalah contoh lain dari fungsi dasar yang menggunakan Integer sebagai masukan, tetapi dalam kasus ini, mengembalikan Boolean untuk menunjukkan apakah masukan genap atau ganjil:

public static final F isEven = i -> i % 2 == 0;

5. Menerapkan Fungsi

Sekarang setelah kita memiliki fungsi, mari kita terapkan ke dataset.

Pustaka Java Fungsional menyediakan sekumpulan tipe biasa untuk mengelola data seperti daftar, set, array, dan peta. Hal utama yang harus disadari adalah bahwa tipe data ini tidak dapat diubah.

Selain itu, pustaka menyediakan fungsi praktis untuk mengonversi ke dan dari kelas Koleksi Java standar jika diperlukan.

Dalam contoh di bawah ini, kita akan mendefinisikan daftar integer dan menerapkan fungsi timesTwo kita padanya. Kami juga akan memanggil peta menggunakan definisi sebaris dari fungsi yang sama. Tentu saja, kami mengharapkan hasil yang sama:

public void multiplyNumbers_givenIntList_returnTrue() { List fList = List.list(1, 2, 3, 4); List fList1 = fList.map(timesTwo); List fList2 = fList.map(i -> i * 2); assertTrue(fList1.equals(fList2)); }

Seperti yang bisa kita lihat, map mengembalikan daftar dengan ukuran yang sama di mana setiap nilai elemen adalah nilai dari daftar input dengan fungsi yang diterapkan. Daftar masukan itu sendiri tidak berubah.

Berikut contoh serupa menggunakan fungsi isEven kami :

public void calculateEvenNumbers_givenIntList_returnTrue() { List fList = List.list(3, 4, 5, 6); List evenList = fList.map(isEven); List evenListTrueResult = List.list(false, true, false, true); assertTrue(evenList.equals(evenListTrueResult)); }

Karena metode map mengembalikan daftar, kita dapat menerapkan fungsi lain ke keluarannya. Urutan di mana kita menjalankan fungsi peta kita mengubah keluaran yang kita hasilkan:

public void applyMultipleFunctions_givenIntList_returnFalse() { List fList = List.list(1, 2, 3, 4); List fList1 = fList.map(timesTwo).map(plusOne); List fList2 = fList.map(plusOne).map(timesTwo); assertFalse(fList1.equals(fList2)); }

Output dari daftar di atas adalah:

List(3,5,7,9) List(4,6,8,10)

6. Memfilter Menggunakan Fungsi

Operasi lain yang sering digunakan dalam Pemrograman Fungsional adalah mengambil input dan menyaring data berdasarkan beberapa kriteria . Dan seperti yang mungkin sudah Anda duga, kriteria pemfilteran ini disediakan dalam bentuk fungsi. Fungsi ini perlu mengembalikan boolean untuk menunjukkan apakah data perlu disertakan dalam keluaran atau tidak.

Sekarang, mari gunakan fungsi isEven untuk menyaring angka ganjil dari larik input menggunakan metode filter :

public void filterList_givenIntList_returnResult() { Array array = Array.array(3, 4, 5, 6); Array filteredArray = array.filter(isEven); Array result = Array.array(4, 6); assertTrue(filteredArray.equals(result)); }

Satu pengamatan yang menarik adalah bahwa dalam contoh ini, kami menggunakan Array alih-alih List seperti yang kami gunakan dalam contoh sebelumnya, dan fungsi kami berfungsi dengan baik. Karena cara fungsi diabstraksi dan dijalankan, mereka tidak perlu mengetahui metode apa yang digunakan untuk mengumpulkan masukan dan keluaran.

Dalam contoh ini, kami juga menggunakan fungsi isEven kami sendiri , tetapi kelas Integer Fungsional Java juga memiliki fungsi standar untuk perbandingan numerik dasar.

7. Menerapkan Logika Boolean Menggunakan Fungsi

Dalam Pemrograman Fungsional, kita sering menggunakan logika seperti “hanya lakukan ini jika semua elemen memenuhi beberapa kondisi”, atau “lakukan ini hanya jika setidaknya satu elemen memenuhi beberapa kondisi”.

Perpustakaan Java Fungsional memberikan kita jalan pintas untuk logika ini melalui ada dan forall metode:

public void checkForLowerCase_givenStringArray_returnResult() { Array array = Array.array("Welcome", "To", "baeldung"); assertTrue(array.exists(s -> List.fromString(s).forall(Characters.isLowerCase))); Array array2 = Array.array("Welcome", "To", "Baeldung"); assertFalse(array2.exists(s -> List.fromString(s).forall(Characters.isLowerCase))); assertFalse(array.forall(s -> List.fromString(s).forall(Characters.isLowerCase))); }

Dalam contoh di atas, kami menggunakan array string sebagai masukan kami. Memanggil fungsi fromString akan mengubah setiap string dari array menjadi daftar karakter. Untuk masing-masing daftar itu, kami menerapkan untuk semua (Characters.isLowerCase) .

Seperti yang mungkin Anda tebak, Characters.isLowerCase adalah fungsi yang mengembalikan nilai true jika karakter menggunakan huruf kecil. Jadi menerapkan forall (Characters.isLowerCase) ke daftar karakter hanya akan mengembalikan nilai true jika seluruh daftar terdiri dari karakter huruf kecil, yang kemudian menunjukkan bahwa string asli adalah huruf kecil semua.

In the first two tests, we used exists because we only wanted to know whether at least one string was lowercase. The third test used forall to verify whether all strings were lowercase.

8. Handling Optional Values With a Function

Handling optional values in code typically requires == null or isNotBlank checks. Java 8 now provides the Optional class to handle these checks more elegantly, and the Functional Java library offers a similar construct to deal with missing data gracefully through its Option class:

public void checkOptions_givenOptions_returnResult() { Option n1 = Option.some(1); Option n2 = Option.some(2); Option n3 = Option.none(); F
    
      function = i -> i % 2 == 0 ? Option.some(i + 100) : Option.none(); Option result1 = n1.bind(function); Option result2 = n2.bind(function); Option result3 = n3.bind(function); assertEquals(Option.none(), result1); assertEquals(Option.some(102), result2); assertEquals(Option.none(), result3); }
    

9. Reducing a Set Using a Function

Finally, we will look at functionality to reduce a set. “Reducing a set” is a fancy way of saying “rolling it up into one value”.

Pustaka Java Fungsional menyebut fungsi ini sebagai pelipatan .

Sebuah fungsi perlu ditentukan untuk menunjukkan apa artinya melipat elemen. Contoh dari ini adalah fungsi Integers.add untuk menunjukkan bilangan bulat dalam array atau daftar perlu ditambahkan.

Berdasarkan fungsinya saat melipat, hasilnya bisa berbeda tergantung apakah Anda mulai melipat dari kanan atau kiri. Itulah mengapa pustaka Java Fungsional menyediakan kedua versi:

public void foldLeft_givenArray_returnResult() { Array intArray = Array.array(17, 44, 67, 2, 22, 80, 1, 27); int sumAll = intArray.foldLeft(Integers.add, 0); assertEquals(260, sumAll); int sumEven = intArray.filter(isEven).foldLeft(Integers.add, 0); assertEquals(148, sumEven); }

FoldLeft pertama hanya menambahkan semua bilangan bulat. Sedangkan yang kedua akan menerapkan filter dan kemudian menambahkan bilangan bulat yang tersisa.

10. Kesimpulan

Artikel ini hanyalah pengenalan singkat tentang pustaka Java Fungsional.

Seperti biasa, kode sumber lengkap artikel tersedia di GitHub.