Introduksjon til funksjonell Java

1. Oversikt

I denne veiledningen gir vi en rask oversikt over det funksjonelle Java-biblioteket sammen med noen få eksempler.

2. Det funksjonelle Java-biblioteket

Det funksjonelle Java-biblioteket er et open source-bibliotek som er ment for å lette funksjonell programmering i Java. Biblioteket tilbyr mange grunnleggende og avanserte programmeringsabstraksjoner som ofte brukes i funksjonell programmering.

Mye av bibliotekets funksjonalitet dreier seg om F grensesnitt. Dette F grensesnitt modellerer en funksjon som tar en inngang av typen EN og returnerer en output av typen B. Alt dette er bygget oppå Java sitt eget typesystem.

3. Maven-avhengigheter

Først må vi legge til de nødvendige avhengighetene til vår 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. Definere en funksjon

La oss starte med å lage en funksjon som vi kan bruke i eksemplene våre senere.

Uten funksjonell Java vil en grunnleggende multiplikasjonsmetode se ut som:

offentlig statisk slutt Heltall gangerToRegular (Heltall i) {retur i * 2; }

Ved å bruke det funksjonelle Java-biblioteket kan vi definere denne funksjonaliteten litt mer elegant:

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

Ovenfor ser vi et eksempel på F grensesnitt som tar et Heltall som input og returnerer det Heltall ganger to som utdata.

Her er et annet eksempel på en grunnleggende funksjon som tar en Heltall som input, men i dette tilfellet, returnerer a Boolsk for å indikere om inngangen var jevn eller merkelig:

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

5. Bruke en funksjon

Nå som vi har funksjonene våre på plass, la oss bruke dem på et datasett.

Det funksjonelle Java-biblioteket gir det vanlige settet med typer for administrering av data som lister, sett, matriser og kart. Det viktigste å innse er at disse datatypene er uforanderlige.

I tillegg tilbyr biblioteket bekvemmelighetsfunksjoner for å konvertere til og fra standard Java Collections-klasser hvis nødvendig.

I eksemplet nedenfor definerer vi en liste over heltall og bruker vårt timesTwo funksjon til den. Vi ringer også kart ved hjelp av en innebygd definisjon av samme funksjon. Selvfølgelig forventer vi at resultatene blir de samme:

offentlig ugyldig 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 kart returnerer en liste med samme størrelse der hvert elements verdi er verdien på inngangslisten med funksjonen som brukes. Selve inngangslisten endres ikke.

Her er et lignende eksempel som bruker vår isEven funksjon:

offentlig tomrom 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 kart metoden returnerer en liste, kan vi bruke en annen funksjon på utgangen. Rekkefølgen vi påberoper oss kart funksjoner endrer den resulterende produksjonen vår:

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 av listene ovenfor vil være:

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

6. Filtrering ved hjelp av en funksjon

En annen ofte brukt operasjon i funksjonell programmering er å ta en innspill og filtrer ut data basert på noen kriterier. Og som du sikkert allerede har gjettet, er disse filtreringskriteriene gitt i form av en funksjon. Denne funksjonen må returnere en boolsk for å indikere om dataene må inkluderes i utdataene.

La oss nå bruke vår isEven funksjon for å filtrere ut oddetallene fra et inngangssett ved hjelp av 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 observasjon er at vi i dette eksemplet brukte en Array i stedet for en Liste som vi brukte i tidligere eksempler, og funksjonen vår fungerte bra. På grunn av måten funksjoner blir abstrakt og utført, trenger de ikke å være klar over hvilken metode som ble brukt til å samle inn og ut.

I dette eksemplet brukte vi også vårt eget isEven funksjon, men Funksjonell Java sin egen Heltall klasse har også standardfunksjoner for grunnleggende numeriske sammenligninger.

7. Bruke boolsk logikk ved hjelp av en funksjon

I funksjonell programmering bruker vi ofte logikk som "bare gjør dette hvis alle elementene tilfredsstiller noen tilstand", eller "bare gjør dette hvis minst ett element tilfredsstiller noen tilstand".

Det funksjonelle Java-biblioteket gir oss snarveier til denne logikken gjennom 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 ("Welcome", "To", "Baeldung"); assertFalse (array2.exists (s -> List.fromString (s) .forall (Characters.isLowerCase))); assertFalse (array.forall (s -> List.fromString (s) .forall (Characters.isLowerCase))); }

I eksemplet ovenfor brukte vi en rekke strenger som vår input. Ringer til fraString funksjon vil konvertere hver av strengene fra matrisen til en liste med tegn. På hver av disse listene søkte vi forall (Characters.isLowerCase).

Som du sannsynligvis gjettet, Tegn.isLowerCase er en funksjon som returnerer sant hvis et tegn er med små bokstaver. Så søker forall (Characters.isLowerCase) til en liste med tegn kommer bare tilbake ekte hvis hele listen består av små bokstaver, som igjen indikerer at den opprinnelige strengen var liten.

I de to første testene brukte vi eksisterer fordi vi bare ønsket å vite om minst en streng var små bokstaver. Den tredje testen som ble brukt for alle for å verifisere om alle strengene var små.

8. Håndtering av valgfrie verdier med en funksjon

Håndtering av valgfrie verdier i kode krever vanligvis == null eller er ikke blank sjekker. Java 8 gir nå Valgfri klasse for å håndtere disse sjekkene mer elegant, og det funksjonelle Java-biblioteket tilbyr en lignende konstruksjon for å håndtere manglende data elegant gjennom sin alternativsklasse:

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

9. Redusere et sett ved hjelp av en funksjon

Til slutt vil vi se på funksjonalitet for å redusere et sett. "Å redusere et sett" er en fancy måte å si "å rulle det opp til en verdi".

Funksjonelt Java-bibliotek refererer til denne funksjonaliteten som folding.

En funksjon må spesifiseres for å indikere hva det betyr å brette elementet. Et eksempel på dette er Heltall. Legge til funksjon for å vise heltallene i en matrise eller liste må legges til.

Basert på hva funksjonen gjør når du bretter, kan resultatet være forskjellig avhengig av om du begynner å brette fra høyre eller venstre. Derfor har det funksjonelle Java-biblioteket begge versjoner:

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

Den første foldLeft bare legger til alle heltallene. Mens det andre først vil bruke et filter og deretter legge til de resterende heltallene.

10. Konklusjon

Denne artikkelen er bare en kort introduksjon til det funksjonelle Java-biblioteket.

Som alltid er hele kildekoden til artikkelen tilgjengelig på GitHub.