Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> Java

Java Lambda-expressies

Java Lambda-expressies

In dit artikel zullen we leren over Java lambda-expressie en het gebruik van lambda-expressie met functionele interfaces, generieke functionele interface en stream-API met behulp van voorbeelden.

De lambda-expressie werd voor het eerst geïntroduceerd in Java 8. Het belangrijkste doel is om de expressieve kracht van de taal te vergroten.

Maar voordat we overgaan op lambda's, moeten we eerst de functionele interfaces begrijpen.


Wat is een functionele interface?

Als een Java-interface één en slechts één abstracte methode bevat, wordt dit een functionele interface genoemd. Deze enige methode specificeert het beoogde doel van de interface.

Bijvoorbeeld de Runnable interface uit pakket java.lang; is een functionele interface omdat het slechts één methode vormt, namelijk run() .

Voorbeeld 1:Definieer een functionele interface in java

import java.lang.FunctionalInterface;
@FunctionalInterface
public interface MyInterface{
    // the single abstract method
    double getValue();
}

In het bovenstaande voorbeeld heeft de interface MyInterface slechts één abstracte methode getValue(). Het is dus een functionele interface.

Hier hebben we de annotatie @FunctionalInterface . gebruikt . De annotatie dwingt de Java-compiler om aan te geven dat de interface een functionele interface is. Staat daarom niet toe om meer dan één abstracte methode te hebben. Het is echter niet verplicht.

In Java 7 werden functionele interfaces beschouwd als Single Abstract Methods of SAM type. SAM's werden vaak geïmplementeerd met anonieme klassen in Java 7.

Voorbeeld 2:Implementeer SAM met anonieme klassen in java

public class FunctionInterfaceTest {
    public static void main(String[] args) {

        // anonymous class
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("I just implemented the Runnable Functional Interface.");
            }
        }).start();
    }
}

Uitvoer :

I just implemented the Runnable Functional Interface.

Hier kunnen we een anonieme klasse doorgeven aan een methode. Dit helpt om programma's met minder codes in Java 7 te schrijven. De syntaxis was echter nog steeds moeilijk en er waren veel extra regels code nodig.

Java 8 breidde de kracht van een SAM uit door een stap verder te gaan. Aangezien we weten dat een functionele interface slechts één methode heeft, zou het niet nodig moeten zijn om de naam van die methode te definiëren wanneer deze als argument wordt doorgegeven. Lambda-expressie stelt ons in staat om precies dat te doen.


Inleiding tot lambda-expressies

Lambda-expressie is in wezen een anonieme of naamloze methode. De lambda-expressie wordt niet vanzelf uitgevoerd. In plaats daarvan wordt het gebruikt om een ​​methode te implementeren die wordt gedefinieerd door een functionele interface.

Hoe lambda-expressie in Java definiëren?

Hier is hoe we lambda-expressie in Java kunnen definiëren.

(parameter list) -> lambda body

De nieuwe operator (-> ) gebruikt staat bekend als een pijl-operator of een lambda-operator. De syntaxis is op dit moment misschien niet duidelijk. Laten we enkele voorbeelden bekijken,

Stel dat we een methode hebben zoals deze:

double getPiValue() {
    return 3.1415;
}

We kunnen deze methode met lambda-expressie schrijven als:

() -> 3.1415

Hier heeft de methode geen parameters. Daarom bevat de linkerkant van de operator een lege parameter. De rechterkant is de lambda-body die de actie van de lambda-expressie specificeert. In dit geval geeft het de waarde 3.1415 terug.


Soorten lambdalichaam

In Java bestaat het lambdalichaam uit twee typen.

1. Een lichaam met een enkele uitdrukking

() -> System.out.println("Lambdas are great");

Dit type lambdalichaam staat bekend als het expressielichaam.

2. Een body die uit een codeblok bestaat.

() -> {
    double pi = 3.1415;
    return pi;
};

Dit type lambdalichaam staat bekend als een bloklichaam. Met het bloklichaam kan het lambdalichaam meerdere verklaringen opnemen. Deze uitspraken staan ​​tussen de accolades en u moet een puntkomma toevoegen na de accolades.

Opmerking :Voor de body van het blok kunt u een return-statement hebben als de body een waarde retourneert. De hoofdtekst van de expressie vereist echter geen return-instructie.


Voorbeeld 3:Lambda-expressie

Laten we een Java-programma schrijven dat de waarde van Pi retourneert met behulp van de lambda-expressie.

Zoals eerder vermeld, wordt een lambda-expressie niet op zichzelf uitgevoerd. Het vormt eerder de implementatie van de abstracte methode gedefinieerd door de functionele interface.

We moeten dus eerst een functionele interface definiëren.

import java.lang.FunctionalInterface;

// this is functional interface
@FunctionalInterface
interface MyInterface{

    // abstract method
    double getPiValue();
}

public class Main {

    public static void main( String[] args ) {

    // declare a reference to MyInterface
    MyInterface ref;
    
    // lambda expression
    ref = () -> 3.1415;
    
    System.out.println("Value of Pi = " + ref.getPiValue());
    } 
}

Uitvoer :

Value of Pi = 3.1415

In het bovenstaande voorbeeld,

  • We hebben een functionele interface gemaakt met de naam MyInterface . Het bevat een enkele abstracte methode genaamd getPiValue()
  • Binnen de Hoofd class hebben we een verwijzing naar MyInterface . Merk op dat we een referentie van een interface kunnen declareren, maar dat we geen interface kunnen instantiëren. Dat is,
    // it will throw an error
    MyInterface ref = new myInterface();
    
    // it is valid
    MyInterface ref;
  • Vervolgens hebben we een lambda-expressie toegewezen aan de referentie.
    ref = () -> 3.1415;
  • Ten slotte noemen we de methode getPiValue() met behulp van de referentie-interface. Wanneer
    System.out.println("Value of Pi = " + ref.getPiValue());

Lambda-expressies met parameters

Tot nu toe hebben we lambda-expressies gemaakt zonder parameters. Net als bij methoden kunnen lambda-expressies echter ook parameters hebben. Bijvoorbeeld,

(n) -> (n%2)==0

Hier is de variabele n tussen haakjes een parameter die wordt doorgegeven aan de lambda-expressie. Het lambdalichaam neemt de parameter en controleert of deze even of oneven is.

Voorbeeld 4:Lambda-expressie gebruiken met parameters

@FunctionalInterface
interface MyInterface {

    // abstract method
    String reverse(String n);
}

public class Main {

    public static void main( String[] args ) {

        // declare a reference to MyInterface
        // assign a lambda expression to the reference
        MyInterface ref = (str) -> {

            String result = "";
            for (int i = str.length()-1; i >= 0 ; i--)
            result += str.charAt(i);
            return result;
        };

        // call the method of the interface
        System.out.println("Lambda reversed = " + ref.reverse("Lambda"));
    }

}

Uitvoer :

Lambda reversed = adbmaL

Algemene functionele interface

Tot nu toe hebben we de functionele interface gebruikt die slechts één type waarde accepteert. Bijvoorbeeld,

@FunctionalInterface
interface MyInterface {
    String reverseString(String n);
}

De bovenstaande functionele interface accepteert alleen String en retourneert String . We kunnen de functionele interface echter generiek maken, zodat elk gegevenstype wordt geaccepteerd. Als u niet zeker bent van generieke geneesmiddelen, gaat u naar Java Generics.

Voorbeeld 5:Algemene functionele interface en Lambda-expressies

// GenericInterface.java
@FunctionalInterface
interface GenericInterface<T> {

    // generic method
    T func(T t);
}

// GenericLambda.java
public class Main {

    public static void main( String[] args ) {

        // declare a reference to GenericInterface
        // the GenericInterface operates on String data
        // assign a lambda expression to it
        GenericInterface<String> reverse = (str) -> {

            String result = "";
            for (int i = str.length()-1; i >= 0 ; i--)
            result += str.charAt(i);
            return result;
        };

        System.out.println("Lambda reversed = " + reverse.func("Lambda"));

        // declare another reference to GenericInterface
        // the GenericInterface operates on Integer data
        // assign a lambda expression to it
        GenericInterface<Integer> factorial = (n) -> {

            int result = 1;
            for (int i = 1; i <= n; i++)
            result = i * result;
            return result;
        };

        System.out.println("factorial of 5 = " + factorial.func(5));
    }
}

Uitvoer :

Lambda reversed = adbmaL
factorial of 5 = 120

In het bovenstaande voorbeeld hebben we een generieke functionele interface gemaakt met de naam GenericInterface . Het bevat een generieke methode genaamd func() .

Hier, in de hoofdklasse,

  • GenericInterface<String> reverse - creëert een verwijzing naar de interface. De interface werkt nu op String type gegevens.
  • GenericInterface<Integer> factorial - creëert een verwijzing naar de interface. De interface werkt in dit geval op de Integer type gegevens.

Lambda Expression en Stream API

Het nieuwe pakket java.util.stream is toegevoegd aan JDK8, waarmee Java-ontwikkelaars bewerkingen kunnen uitvoeren zoals zoeken, filteren, in kaart brengen, verkleinen of manipuleren van collecties zoals Lists .

We hebben bijvoorbeeld een gegevensstroom (in ons geval een List van String ) waarbij elke tekenreeks een combinatie is van de landnaam en de plaats van het land. Nu kunnen we deze gegevensstroom verwerken en alleen de plaatsen uit Nepal ophalen.

Hiervoor kunnen we bulkbewerkingen in de stream uitvoeren door de combinatie van Stream API en Lambda-expressie.

Voorbeeld 6:Demonstratie van het gebruik van lambda's met de Stream API

import java.util.ArrayList;
import java.util.List;

public class StreamMain {

    // create an object of list using ArrayList
    static List<String> places = new ArrayList<>();

    // preparing our data
    public static List getPlaces(){

        // add places and country to the list
        places.add("Nepal, Kathmandu");
        places.add("Nepal, Pokhara");
        places.add("India, Delhi");
        places.add("USA, New York");
        places.add("Africa, Nigeria");

        return places;
    }

    public static void main( String[] args ) {

        List<String> myPlaces = getPlaces();
        System.out.println("Places from Nepal:");
        
        // Filter places from Nepal
        myPlaces.stream()
                .filter((p) -> p.startsWith("Nepal"))
                .map((p) -> p.toUpperCase())
                .sorted()
                .forEach((p) -> System.out.println(p));
    }

}

Uitvoer :

Places from Nepal:
NEPAL, KATHMANDU
NEPAL, POKHARA

Let in het bovenstaande voorbeeld op de verklaring,

myPlaces.stream()
        .filter((p) -> p.startsWith("Nepal"))
        .map((p) -> p.toUpperCase())
        .sorted()
        .forEach((p) -> System.out.println(p));

Hier gebruiken we de methoden zoals filter() , map() en forEach() van de Stream-API. Deze methoden kunnen een lambda-expressie als invoer hebben.

We kunnen ook onze eigen uitdrukkingen definiëren op basis van de syntaxis die we hierboven hebben geleerd. Dit stelt ons in staat om de regels code drastisch te verminderen, zoals we in het bovenstaande voorbeeld zagen.


Java

  1. C#-interface
  2. Java-operators
  3. Java-uitdrukkingen, verklaringen en blokken
  4. Java-interface
  5. Java proberen-met-bronnen
  6. Java-annotaties
  7. Interface versus abstracte klasse in Java:wat is het verschil?
  8. Java - Reguliere expressies
  9. Java - Interfaces
  10. Java 9 - Privé-interfacemethoden
  11. Java 8 - Lambda-expressies