Pengenalan Java Berfungsi

1. Gambaran keseluruhan

Dalam tutorial ini, kami akan memberikan gambaran ringkas mengenai perpustakaan Java Fungsional bersama dengan beberapa contoh.

2. Perpustakaan Java Berfungsi

Perpustakaan Java Fungsional adalah perpustakaan sumber terbuka yang dimaksudkan untuk memfasilitasi pengaturcaraan fungsional di Java. Perpustakaan menyediakan banyak abstraksi pengaturcaraan asas dan lanjutan yang biasa digunakan dalam Pengaturcaraan Fungsional.

Sebilangan besar fungsi perpustakaan berkisar pada antara muka F. Ini F antara muka model fungsi yang mengambil input jenis A dan mengembalikan output jenis B . Semua ini dibina berdasarkan sistem jenis Java sendiri.

3. Pergantungan Maven

Pertama, kita perlu menambahkan kebergantungan yang diperlukan ke fail pom.xml kami :

 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 mulakan dengan membuat fungsi yang boleh kita gunakan dalam contoh kita di kemudian hari.

Tanpa Java Fungsional, kaedah pendaraban asas akan kelihatan seperti:

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

Dengan menggunakan perpustakaan Java Fungsional, kita dapat menentukan fungsi ini sedikit lebih elegan:

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

Di atas, kita melihat contoh antara muka F yang mengambil Integer sebagai input dan mengembalikan Integer dua kali ganda sebagai outputnya.

Berikut adalah contoh fungsi asas yang mengambil Integer sebagai input, tetapi dalam kes ini, mengembalikan Boolean untuk menunjukkan sama ada inputnya genap atau ganjil:

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

5. Mengaplikasi Fungsi

Sekarang kita mempunyai fungsi kita, mari kita terapkan pada set data.

Perpustakaan Java Fungsional menyediakan sekumpulan jenis biasa untuk menguruskan data seperti senarai, set, tatasusunan, dan peta. Perkara utama yang perlu disedari ialah jenis data ini tidak berubah.

Selain itu, perpustakaan menyediakan fungsi kemudahan untuk menukar ke dan dari kelas Koleksi Java standard jika diperlukan.

Dalam contoh di bawah ini, kami akan menentukan senarai bilangan bulat dan menggunakan fungsi timeTwo untuknya. Kami juga akan memanggil peta menggunakan definisi sebaris fungsi yang sama. Sudah tentu, kami menjangkakan hasilnya 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 kita lihat peta mengembalikan senarai dengan ukuran yang sama di mana nilai setiap elemen adalah nilai senarai input dengan fungsi yang diterapkan. Senarai input itu sendiri tidak berubah.

Berikut adalah contoh yang 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)); }

Oleh kerana kaedah peta mengembalikan senarai, kita dapat menerapkan fungsi lain pada outputnya. Urutan penggunaan fungsi peta mengubah output yang dihasilkan:

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)); }

Hasil senarai di atas adalah:

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

6. Menapis Menggunakan Fungsi

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

Sekarang, mari gunakan fungsi isEven kami untuk menyaring nombor ganjil dari array input menggunakan kaedah penapis :

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 pemerhatian yang menarik adalah bahawa dalam contoh ini, kita menggunakan Array dan bukannya Daftar seperti yang kita gunakan dalam contoh sebelumnya, dan fungsi kita berfungsi dengan baik. Kerana cara fungsi diabstrak dan dilaksanakan, mereka tidak perlu mengetahui metode apa yang digunakan untuk mengumpulkan input dan output.

Dalam contoh ini, kami juga menggunakan fungsi isEven kami sendiri , tetapi kelas Integer Java Fungsional sendiri juga mempunyai fungsi standard untuk perbandingan numerik asas.

7. Menerapkan Logik Boolean Menggunakan Fungsi

Dalam Pengaturcaraan Fungsional, kami sering menggunakan logik seperti "hanya melakukan ini jika semua elemen memenuhi beberapa syarat", atau "hanya melakukan ini jika sekurang-kurangnya satu elemen memenuhi beberapa syarat".

Perpustakaan Fungsional Java memberi kita jalan pintas untuk logik ini melalui kaedah yang ada dan forall :

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 pelbagai rentetan sebagai input kami. Memanggil fungsi fromString akan menukar setiap rentetan dari array menjadi senarai watak. Untuk setiap senarai tersebut, kami menggunakan forall (Characters.isLowerCase) .

Seperti yang anda duga, Characters.isLowerCase adalah fungsi yang kembali benar jika watak adalah huruf kecil. Oleh itu, memohon forall (Characters.isLowerCase) ke senarai watak hanya akan kembali benar jika keseluruhan senarai terdiri daripada huruf kecil, yang kemudian menunjukkan bahawa rentetan asalnya adalah huruf kecil.

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”.

Perpustakaan Fungsional Java merujuk fungsi ini sebagai lipat .

Fungsi perlu ditentukan untuk menunjukkan apa maksud melipat elemen. Contohnya ialah fungsi Integers.add untuk menunjukkan bilangan bulat dalam array atau senarai yang perlu ditambahkan.

Berdasarkan fungsi yang dilakukan semasa melipat, hasilnya boleh berbeza bergantung pada sama ada anda mula melipat dari kanan atau kiri. Itulah sebabnya perpustakaan Fungsional Java menyediakan kedua-dua 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); }

Lipatan Kiri pertama hanya menambah semua bilangan bulat. Manakala yang kedua akan menggunakan penapis dan kemudian menambahkan bilangan bulat yang tinggal.

10. Kesimpulannya

Artikel ini hanyalah pengenalan ringkas ke perpustakaan Java Fungsional.

Seperti biasa, kod sumber penuh artikel terdapat di GitHub.