Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Java

Expressions Java Lambda

Expressions Lambda Java

Dans cet article, nous découvrirons l'expression lambda Java et l'utilisation de l'expression lambda avec des interfaces fonctionnelles, une interface fonctionnelle générique et une API de flux à l'aide d'exemples.

L'expression lambda a été introduite pour la première fois dans Java 8. Son objectif principal est d'augmenter la puissance expressive du langage.

Mais, avant d'entrer dans les lambdas, nous devons d'abord comprendre les interfaces fonctionnelles.

Qu'est-ce que l'interface fonctionnelle ?

Si une interface Java contient une et une seule méthode abstraite, elle est appelée interface fonctionnelle. Cette seule méthode spécifie le but prévu de l'interface.

Par exemple, le Runnable interface du paquet java.lang; est une interface fonctionnelle car elle ne constitue qu'une seule méthode soit run() .

Exemple 1 :Définir une interface fonctionnelle en Java

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

Dans l'exemple ci-dessus, l'interface MyInterface n'a qu'une seule méthode abstraite getValue(). Il s'agit donc d'une interface fonctionnelle.

Ici, nous avons utilisé l'annotation @FunctionalInterface . L'annotation force le compilateur Java à indiquer que l'interface est une interface fonctionnelle. Par conséquent, ne permet pas d'avoir plus d'une méthode abstraite. Cependant, ce n'est pas obligatoire.

Dans Java 7, les interfaces fonctionnelles étaient considérées comme des méthodes abstraites uniques ou SAM taper. Les SAM étaient généralement implémentés avec des classes anonymes dans Java 7.

Exemple 2 :Implémenter SAM avec des classes anonymes en 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();
    }
}

Sortie :

I just implemented the Runnable Functional Interface.

Ici, nous pouvons passer une classe anonyme à une méthode. Cela aide à écrire des programmes avec moins de codes en Java 7. Cependant, la syntaxe était encore difficile et de nombreuses lignes de code supplémentaires étaient nécessaires.

Java 8 a étendu la puissance d'un SAM en allant encore plus loin. Puisque nous savons qu'une interface fonctionnelle n'a qu'une seule méthode, il ne devrait pas être nécessaire de définir le nom de cette méthode lors de sa transmission en argument. L'expression lambda nous permet de faire exactement cela.

Introduction aux expressions lambda

L'expression Lambda est, essentiellement, une méthode anonyme ou sans nom. L'expression lambda ne s'exécute pas toute seule. Au lieu de cela, il est utilisé pour implémenter une méthode définie par une interface fonctionnelle.

Comment définir une expression lambda en Java ?

Voici comment nous pouvons définir l'expression lambda en Java.

(parameter list) -> lambda body

Le nouvel opérateur (-> ) utilisé est appelé opérateur fléché ou opérateur lambda. La syntaxe n'est peut-être pas claire pour le moment. Explorons quelques exemples,

Supposons que nous ayons une méthode comme celle-ci :

double getPiValue() {
    return 3.1415;
}

Nous pouvons écrire cette méthode en utilisant l'expression lambda comme :

() -> 3.1415

Ici, la méthode n'a pas de paramètres. Par conséquent, le côté gauche de l'opérateur inclut un paramètre vide. Le côté droit est le corps lambda qui spécifie l'action de l'expression lambda. Dans ce cas, il renvoie la valeur 3.1415.

Types de corps Lambda

En Java, le corps lambda est de deux types.

1. Un corps avec une seule expression

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

Ce type de corps lambda est connu sous le nom de corps d'expression.

2. Corps constitué d'un bloc de code.

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

Ce type de corps lambda est connu sous le nom de corps de bloc. Le corps du bloc permet au corps lambda d'inclure plusieurs instructions. Ces déclarations sont entre accolades et vous devez ajouter un point-virgule après les accolades.

Remarque :Pour le corps du bloc, vous pouvez avoir une instruction return si le corps renvoie une valeur. Cependant, le corps de l'expression ne nécessite pas d'instruction return.

Exemple 3 :Expression Lambda

Écrivons un programme Java qui renvoie la valeur de Pi en utilisant l'expression lambda.

Comme mentionné précédemment, une expression lambda n'est pas exécutée seule. Il constitue plutôt l'implémentation de la méthode abstraite définie par l'interface fonctionnelle.

Nous devons donc d'abord définir une interface fonctionnelle.

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

Sortie :

Value of Pi = 3.1415

Dans l'exemple ci-dessus,

  • Nous avons créé une interface fonctionnelle nommée MyInterface . Il contient une seule méthode abstraite nommée getPiValue()
  • À l'intérieur de la Principale class, nous avons déclaré une référence à MyInterface . Notez que nous pouvons déclarer une référence d'interface mais nous ne pouvons pas instancier une interface. C'est-à-dire,
    // it will throw an error
    MyInterface ref = new myInterface();
    
    // it is valid
    MyInterface ref;
  • Nous avons ensuite attribué une expression lambda à la référence.
    ref = () -> 3.1415;
  • Enfin, nous appelons la méthode getPiValue() à l'aide de l'interface de référence. Lorsque
    System.out.println("Value of Pi = " + ref.getPiValue());

Expressions Lambda avec paramètres

Jusqu'à présent, nous avons créé des expressions lambda sans aucun paramètre. Cependant, à l'instar des méthodes, les expressions lambda peuvent également avoir des paramètres. Par exemple,

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

Ici, la variable n entre parenthèses est un paramètre passé à l'expression lambda. Le corps lambda prend le paramètre et vérifie s'il est pair ou impair.

Exemple 4 :Utilisation d'une expression lambda avec des paramètres

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

}

Sortie :

Lambda reversed = adbmaL

Interface fonctionnelle générique

Jusqu'à présent, nous avons utilisé l'interface fonctionnelle qui n'accepte qu'un seul type de valeur. Par exemple,

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

L'interface fonctionnelle ci-dessus n'accepte que String et renvoie String . Cependant, nous pouvons rendre l'interface fonctionnelle générique, de sorte que n'importe quel type de données soit accepté. Si vous n'êtes pas sûr des génériques, visitez Java Generics.

Exemple 5 :Interface fonctionnelle générique et expressions Lambda

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

Sortie :

Lambda reversed = adbmaL
factorial of 5 = 120

Dans l'exemple ci-dessus, nous avons créé une interface fonctionnelle générique nommée GenericInterface . Il contient une méthode générique nommée func() .

Ici, à l'intérieur de la classe Main,

  • GenericInterface<String> reverse - crée une référence à l'interface. L'interface fonctionne maintenant sur String type de données.
  • GenericInterface<Integer> factorial - crée une référence à l'interface. L'interface, dans ce cas, fonctionne sur le Integer type de données.

API Lambda Expression et Stream

Le nouveau package java.util.stream a été ajouté à JDK8, ce qui permet aux développeurs Java d'effectuer des opérations telles que rechercher, filtrer, mapper, réduire ou manipuler des collections telles que Lists .

Par exemple, nous avons un flux de données (dans notre cas un List de String ) où chaque chaîne est une combinaison du nom du pays et du lieu du pays. Désormais, nous pouvons traiter ce flux de données et récupérer uniquement les lieux du Népal.

Pour cela, nous pouvons effectuer des opérations en bloc dans le flux en combinant l'API Stream et l'expression Lambda.

Exemple 6 : Démonstration de l'utilisation de lambdas avec l'API Stream

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

}

Sortie :

Places from Nepal:
NEPAL, KATHMANDU
NEPAL, POKHARA

Dans l'exemple ci-dessus, notez la déclaration,

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

Ici, nous utilisons les méthodes comme filter() , map() et forEach() de l'API de flux. Ces méthodes peuvent accepter une expression lambda en entrée.

Nous pouvons également définir nos propres expressions en fonction de la syntaxe que nous avons apprise ci-dessus. Cela nous permet de réduire drastiquement les lignes de code comme nous l'avons vu dans l'exemple ci-dessus.


Java

  1. Interface C#
  2. Opérateurs Java
  3. Expressions, instructions et blocs Java
  4. InterfaceJava
  5. Java essayer avec des ressources
  6. Annotations Java
  7. Interface vs classe abstraite en Java :quelle est la différence ?
  8. Java - Expressions régulières
  9. Java-Interfaces