Uvod u funkcionalnu Javu

1. Pregled

U ovom uputstvu pružit ćemo brz pregled funkcionalne Java biblioteke, zajedno s nekoliko primjera.

2. Funkcionalna Java knjižnica

Funkcionalna Java knjižnica je biblioteka otvorenog koda namijenjena olakšavanju funkcionalnog programiranja u Javi. Biblioteka nudi mnoštvo osnovnih i naprednih programskih sažetaka koji se obično koriste u funkcionalnom programiranju.

Većina funkcionalnosti knjižnice vrti se oko F sučelje. Ovaj F sučelje modelira funkciju koja uzima unos tipa A i vraća izlaz tipa B. Sve je to izgrađeno na vrhu Javinog sustava tipova.

3. Ovisnosti Mavena

Prvo, trebamo dodati potrebne ovisnosti na naše pom.xml datoteka:

 org.funkcionalna java-funkcionalnajava 4.8.1 org.funkcionalna java-funkcionalnajava-java8 4.8.1 org.funkcionalnajava-funkcionalnajava-quickcheck 4.8.1 

4. Definiranje funkcije

Počnimo s stvaranjem funkcije koju ćemo kasnije moći koristiti u našim primjerima.

Bez funkcionalne Jave osnovna metoda množenja izgledala bi otprilike ovako:

javni statički konačni Integer timesTwoRegular (Integer i) {return i * 2; }

Koristeći funkcionalnu Java knjižnicu, ovu funkcionalnost možemo definirati malo elegantnije:

javni statički konačni F putaTwo = i -> i * 2;

Iznad vidimo primjer F sučelje koje traje Cijeli broj kao ulaz i vraća to Cijeli broj puta dva kao njegov izlaz.

Evo još jednog primjera osnovne funkcije koja uzima Cijeli broj kao ulaz, ali u ovom slučaju vraća a Booleova da naznači je li unos paran ili neparan:

javni statički konačni F isEven = i -> i% 2 == 0;

5. Primjena funkcije

Sad kad imamo svoje funkcije, primijenimo ih na skup podataka.

Funkcionalna Java knjižnica nudi uobičajeni skup tipova za upravljanje podacima poput popisa, skupova, nizova i karata. Ključna stvar koju treba shvatiti je da su ove vrste podataka nepromjenjive.

Uz to, knjižnica nudi praktične funkcije za pretvaranje u i iz standardnih klasa Java Collections Ako je potrebno.

U donjem primjeru definirat ćemo popis cijelih brojeva i primijeniti svoj putaDva funkcioniraju na njemu. Nazvat ćemo i mi karta koristeći ugrađenu definiciju iste funkcije. Naravno, očekujemo da će rezultati biti jednaki:

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

Kao što možemo vidjeti karta vraća popis iste veličine gdje je vrijednost svakog elementa vrijednost popisa unosa s primijenjenom funkcijom. Sama lista unosa se ne mijenja.

Evo sličnog primjera koristeći naš jeČak funkcija:

javna praznina calcuEvenNumbers_givenIntList_returnTrue () {Popis fList = List.list (3, 4, 5, 6); Popis evenList = fList.map (isEven); Lista evenListTrueResult = List.list (false, true, false, true); assertTrue (evenList.equals (evenListTrueResult)); }

Budući da je karta metoda vraća popis, možemo primijeniti drugu funkciju na njegov izlaz. Redoslijed kojim se pozivamo na naš karta funkcije mijenja naš rezultirajući izlaz:

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

Rezultat gore navedenih popisa bit će:

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

6. Filtriranje pomoću funkcije

Druga često korištena operacija u funkcionalnom programiranju je uzeti ulaz i filtrirati podatke na temelju nekih kriterija. I kao što ste vjerojatno već pogodili, ovi kriteriji filtriranja pružaju se u obliku funkcije. Ova funkcija trebat će vratiti logičku vrijednost kako bi naznačila trebaju li podaci biti uključeni u izlaz.

A sada, iskoristimo naš jeČak funkcija za filtriranje neparnih brojeva iz ulaznog niza pomoću filtar metoda:

javna void filterList_givenIntList_returnResult () {Niz polja = Polje. niz (3, 4, 5, 6); Niz filteredArray = array.filter (isEven); Rezultat niza = Array.array (4, 6); assertTrue (filteredArray.equals (rezultat)); }

Jedno zanimljivo zapažanje je da smo u ovom primjeru koristili Polje umjesto a Popis kao što smo koristili u prethodnim primjerima, i naša je funkcija dobro funkcionirala. Zbog načina apstrahiranja i izvršavanja funkcija, ne trebaju biti svjesni koja je metoda korištena za prikupljanje ulaznih i izlaznih podataka.

U ovom smo primjeru koristili i svoj jeČak funkcija, ali vlastita Funkcionalna Java Cijeli broj razred također ima standardne funkcije za osnovne numeričke usporedbe.

7. Primjena logičke logike pomoću funkcije

U funkcionalnom programiranju često koristimo logiku poput "učinite to samo ako svi elementi zadovoljavaju neki uvjet" ili "učinite to samo ako barem jedan element zadovoljava neki uvjet".

Funkcionalna Java knjižnica pruža nam prečace za ovu logiku putem postoji i za sve metode:

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

U gornjem primjeru koristili smo niz žica kao svoj ulaz. Pozivanje fromString funkcija pretvorit će svaki niz iz niza u popis znakova. Na svaki od tih popisa primijenili smo se forall (Characters.isLowerCase).

Kao što ste vjerojatno pretpostavili, Znakovi.isLowerCase je funkcija koja vraća vrijednost true ako je znak malim slovima. Dakle, prijavljivanje forall (Characters.isLowerCase) na popis znakova vratit će se samo pravi ako se čitav popis sastoji od malih slova, što zauzvrat znači da je izvorni niz bio malim slovima.

U prva dva testa koristili smo postoji jer smo samo željeli znati je li barem jedan niz mali. Treći korišteni test za sve da provjeri jesu li svi nizovi mali.

8. Rukovanje izbornim vrijednostima s funkcijom

Obično je potrebno rukovanje neobaveznim vrijednostima u kodu == null ili nijePrazno provjere. Java 8 sada nudi Neobvezno klase za elegantnije rukovanje tim provjerama, a biblioteka Funkcionalna Java nudi sličnu konstrukciju za graciozno rješavanje nedostajućih podataka putem svoje klase Option:

public void checkOptions_givenOptions_returnResult () {Opcija n1 = Option.some (1); Opcija n2 = Opcija.neki (2); Opcija n3 = Option.none (); F funkcija = i -> i% 2 == 0? Option.neke (i + 100): Option.none (); Opcija rezultat1 = n1.bind (funkcija); Rezultat opcije2 = n2.bind (funkcija); Rezultat opcije3 = n3.bind (funkcija); assertEquals (Option.none (), rezultat1); assertEquals (Option.some (102), result2); assertEquals (Option.none (), result3); }

9. Smanjivanje skupa pomoću funkcije

Na kraju ćemo se osvrnuti na funkcionalnost za smanjenje skupa. "Smanjivanje skupa" fancy je način da se kaže "zamotavanje u jednu vrijednost".

Funkcionalna Java knjižnica ovu funkcionalnost naziva presavijanjem.

Treba navesti funkciju koja označava što znači presavijanje elementa. Primjer za to je Cijeli brojevi.dodaj treba dodati funkciju za prikaz cijelih brojeva u nizu ili popisu.

Na temelju onoga što funkcija radi pri presavijanju, rezultat može biti različit, ovisno o tome započinjete li presavijati s desne ili lijeve strane. Zato funkcionalna Java knjižnica nudi obje verzije:

javna praznina foldLeft_givenArray_returnResult () {Niz 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); }

Prvi foldLeft jednostavno dodaje sve cijele brojeve. Dok će drugi prvo primijeniti filtar, a zatim dodati preostale cijele brojeve.

10. Zaključak

Ovaj je članak samo kratki uvod u funkcionalnu Java knjižnicu.

Kao i uvijek, puni izvorni kôd članka dostupan je na GitHub-u.