Introduktion til funktionel Java

1. Oversigt

I denne vejledning giver vi et hurtigt overblik over det funktionelle Java-bibliotek sammen med et par eksempler.

2. Det funktionelle Java-bibliotek

Det funktionelle Java-bibliotek er et open source-bibliotek beregnet til at lette funktionel programmering i Java. Biblioteket indeholder masser af grundlæggende og avancerede programmeringsabstraktioner, der ofte bruges i funktionel programmering.

Meget af bibliotekets funktionalitet drejer sig om F interface. Det her F interface modellerer en funktion, der tager et input af typen EN og returnerer en output af typen B. Alt dette er bygget oven på Java's eget typesystem.

3. Maven-afhængigheder

Først skal vi tilføje de krævede afhængigheder til vores pom.xml fil:

 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. Definition af en funktion

Lad os starte med at oprette en funktion, som vi senere kan bruge i vores eksempler.

Uden funktionel Java ville en grundlæggende multiplikationsmetode se ud som:

offentlig statisk endelig Heltal timesTwoRegular (Heltal i) {return i * 2; }

Ved hjælp af det funktionelle Java-bibliotek kan vi definere denne funktionalitet lidt mere elegant:

offentlig statisk endelig F timesTwo = i -> i * 2;

Ovenfor ser vi et eksempel på F interface, der tager en Heltal som input og returnerer det Heltal gange to som output.

Her er et andet eksempel på en grundlæggende funktion, der tager en Heltal som input, men i dette tilfælde returnerer a Boolsk for at angive, om input var lige eller ulige:

offentlig statisk endelig F erEven = i -> i% 2 == 0;

5. Anvendelse af en funktion

Nu hvor vi har vores funktioner på plads, lad os anvende dem på et datasæt.

Det funktionelle Java-bibliotek giver det sædvanlige sæt typer til styring af data som lister, sæt, arrays og kort. Den vigtigste ting at indse er, at disse datatyper er uforanderlige.

Derudover tilbyder biblioteket bekvemmelighedsfunktioner til konvertering til og fra standard Java Collections-klasser hvis det er nødvendigt.

I eksemplet nedenfor definerer vi en liste over heltal og anvender vores timesTwo funktion til det. Vi ringer også kort ved hjælp af en integreret definition af den samme funktion. Selvfølgelig forventer vi, at resultaterne er de samme:

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

Som vi kan se kort returnerer en liste med samme størrelse, hvor hvert elements værdi er værdien af ​​inputlisten med den anvendte funktion. Selve inputlisten ændres ikke.

Her er et lignende eksempel ved hjælp af vores isEven fungere:

offentligt tomrum beregneEvenNumbers_givenIntList_returnTrue () {List fList = List.list (3, 4, 5, 6); Liste evenList = fList.map (isEven); List evenListTrueResult = List.list (false, true, false, true); assertTrue (evenList.equals (evenListTrueResult)); }

Siden den kort metode returnerer en liste, kan vi anvende en anden funktion til dens output. Den rækkefølge, som vi påberåber os kort funktioner ændrer vores resulterende output:

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

Resultatet af ovenstående lister vil være:

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

6. Filtrering ved hjælp af en funktion

En anden hyppig anvendt operation i funktionel programmering er at tage et input og filtrere data baseret på nogle kriterier. Og som du sikkert allerede har gættet, leveres disse filtreringskriterier i form af en funktion. Denne funktion skal returnere en boolsk for at angive, om dataene skal inkluderes i output.

Lad os nu bruge vores isEven funktion til at filtrere de ulige tal fra et input array ved hjælp af filter metode:

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

En interessant bemærkning er, at vi i dette eksempel brugte en Array i stedet for en Liste som vi brugte i tidligere eksempler, og vores funktion fungerede fint. På grund af den måde, hvorpå funktioner abstraheres og udføres, behøver de ikke være opmærksomme på, hvilken metode der blev brugt til at indsamle input og output.

I dette eksempel brugte vi også vores egne isEven funktion, men funktionel Java's egen Heltal klasse har også standardfunktioner til grundlæggende numeriske sammenligninger.

7. Anvendelse af boolsk logik ved hjælp af en funktion

I funktionel programmering bruger vi ofte logik som "gør kun dette, hvis alle elementer opfylder en betingelse" eller "gør kun dette, hvis mindst et element opfylder en eller anden betingelse".

Det funktionelle Java-bibliotek giver os genveje til denne logik gennem eksisterer og for alle metoder:

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 ("Velkommen", "Til", "Baeldung"); assertFalse (array2.exists (s -> List.fromString (s) .forall (Characters.isLowerCase))); assertFalse (array.forall (s -> List.fromString (s) .forall (Characters.isLowerCase))); }

I eksemplet ovenfor brugte vi en række strenge som vores input. Ringer til fraString funktion konverterer hver af strengene fra arrayet til en liste med tegn. På hver af disse lister anvendte vi forall (Characters.isLowerCase).

Som du sandsynligvis gættede, Tegn.isLowerCase er en funktion, der returnerer sand, hvis et tegn er med små bogstaver. Så ansøger forall (Characters.isLowerCase) til en liste med tegn vender kun tilbage rigtigt hvis hele listen består af små bogstaver, hvilket igen indikerer, at den oprindelige streng alle var små bogstaver.

I de to første tests brugte vi eksisterer fordi vi kun ville vide, om mindst én streng var små bogstaver. Den anvendte tredje test for alle for at kontrollere, om alle strenge var små bogstaver.

8. Håndtering af valgfri værdier med en funktion

Håndtering af valgfri værdier i kode kræver typisk == null eller isNotBlank kontrol. Java 8 leverer nu Valgfri klasse til at håndtere disse kontroller mere elegant, og det funktionelle Java-bibliotek tilbyder en lignende konstruktion til at håndtere manglende data yndefuldt gennem sin Option-klasse:

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

9. Reduktion af et sæt ved hjælp af en funktion

Endelig vil vi se på funktionalitet til at reducere et sæt. "At reducere et sæt" er en fancy måde at sige "at rulle det op til en værdi".

Det funktionelle Java-bibliotek henviser til denne funktionalitet som foldning.

En funktion skal specificeres for at angive, hvad det betyder at folde elementet. Et eksempel på dette er Heltal. Tilføj funktion for at vise heltalene i en matrix eller liste skal tilføjes.

Baseret på hvad funktionen gør ved foldning, kan resultatet være forskelligt, afhængigt af om du begynder at folde fra højre eller venstre. Derfor har det funktionelle Java-bibliotek begge versioner:

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

Den første fold venstre tilføjer simpelthen alle heltal. Mens det andet først anvender et filter og derefter tilføjer de resterende heltal.

10. Konklusion

Denne artikel er kun en kort introduktion til det funktionelle Java-bibliotek.

Som altid er artiklens fulde kildekode tilgængelig på GitHub.