Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Definisjonen av funksjonelle grensesnitt er veldig i utgangspunktet enkel: Det er nemlig grensesnitt som har kun én (abstrakt) metode definert. La oss definere Her er et eksempel på dette:

Code Block
themeEclipse
languagejava
titleMultiplier
public interface DoubleValueComputer {
    public double compute(double x, double y);
}

Grensesnittet over er et funksjonelt grensesnitt, for det har bare én metode, nemlig compute. Metoden tar to argumenter, utfører en operasjon på disse, og returnerer resultatet. Forskjellige implementasjoner kan være for eksempel addisjon eller multiplikasjon. I tillegg til å bare ha én metode er det også et krav til, nemlig at objektet som implementerer grensesnittet har dette som sin primære funksjon, og ikke primært er noe annet. Hvis ikke gir det ikke noe mening å lage dem med lambda-uttrykk. Mer om det lenger ned.

Vi kan ta i bruk dette grensesnittet på den tradisjonelle måten ved å opprette en egen klasse som implementerer DoubleValueComptuer, og deretter opprette en Vi kan ta i bruk dette grensesnittet på den tradisjonelle måten ved å opprette en egen klasse som implementerer DoubleValueComptuer, og deretter opprette en instans av denne klassen, som vi kaller compute fra. Men dette blir utrolig tungvint for å bruke en så enkel metode som compute. For å slippe dette lar Java oss definere et objekt som implementerer grensesnittet direkte, ved at man definerer metoden(e) til grensesnittet i initaliseringen av objektet (se venstre kolonne under). Merk at dette fungerer også for grensesnitt med flere metoder.

...

Eksemplene under vil være forskjellige implementasjoner av run()-metoden til PersonMain.java. 

Sortere med Comparator

Å sortere med Comparator blir veldig enkelt med lambda, da Comparator-grensesnittet er funksjonelt. La oss sortere personene på navn (eksempel 1) og på alder (eksempel 2):

Code Block
themeEclipse
languagejava
titleTradisjonell måte
persons.sort(new Comparator<Person>() {
    @Override
    public int compare(Person a, Person b) {
        return a.getName().compareTo(b.getName());
    }
});
Code Block
themeEclipse
languagejava
titleMed stream og lambda
persons.sort((a, b) -> a.getName().compareTo(b.getName()));
Code Block
themeEclipse
languagejava
titleTradisjonell måte
persons.sort(new Comparator<Person>() {
    @Override
    public int compare(Person a, Person b) {
        return a.getAge() - b.getAge();
});
Code Block
themeEclipse
languagejava
titleMed stream og lambda
persons.sort((a, b) -> a.getAge() - b.getAge());

Anchor
comparatorvscomparable
comparatorvscomparable
Comparator vs. Comparable

Comparator er et funksjonelt grensesnitt, men ikke Comparable, selv om Comparable også er et grensesnitt med bare én metode! Dette skyldes det andre kravet nevnt over, nemlig at objektet primært skal være en implementasjon av grensesnittet, og ikke primært noe annen. Grensesnittet Comparable er jo ment å bli implementert av data-klasser som Person, Card osv. og sammenligner typisk objektet selv med et annet av samme type. Objektet er da primært et data-objekt, og implementerer grensesnittet som en sekundært funksjon. Det gir ingen mening å lage et slikt objekt med et lambda-uttrykk, siden den primært funksjonen vil mangle. Comparator kan imidlertid implementeres av en klasse som har det som eneste funksjon og da gir det mening å tillate bruk av lambda-uttrykk for å lage Comparator-implementasjoner.

Se også svaret på et spørsmål om dette på Stack Overflow.

Streams

Streams gjør det veldig enkelt for oss å utføre operasjoner på lister på en kort og elegant måte, i kombinasjon med lambda og ofte Predicate- og Consumer-grensesnittene. I stedet for å forklare hva streams er, skal vi heller vise eksempler på bruken av det.

...