J'ai essayé de résumer les expressions Java lambda

Qu'est-ce qu'une expression lambda?

Nouvelle grammaire introduite dans Java 8. Simplifiez la description du traitement en omettant le contenu décrit à l'aide de la classe locale et de la classe anonyme. Comme exemples typiques, les méthodes de Collections.sort et Stream API ont bénéficié.

Décomposition de l'équation lambda

Les expressions Lambda utilisent un mécanisme appelé classes locales et classes anonymes.

  1. Classe locale

Une classe locale est un mécanisme qui peut être utilisé en déclarant une classe lors du traitement d'une méthode.

public static void main(String[] args) {

  class Local {
    public void sayHello() {
      System.out.println("Hello!");
    }
  }

  Local local = new Local();
  local.sayHello(); // Hello!
}

Vous pouvez également définir une classe locale qui implémente l'interface.

public static void main(String[] args) {

  class Local implements Runnable {
    @Override
    public void run() {
      System.out.println("Hello Lambda!");
    }
  }

  Runnable runner = new Local();
  runner.run(); // Hello Lambda!
}

Ensuite, jetons un œil à la classe anonyme.

  1. Classe anonyme

La classe anonyme est un mécanisme qui omet la déclaration de la classe locale qui implémente l'interface. Voici un exemple de classe anonyme qui implémente l'interface Runnable.

public static void main(String[] args) {

  Runnable runner = new Runnable() {
    @Override
    public void run() {
      System.out.println("Hello Lambda!");
    }
  };

  runner.run(); //Hello Lambda!
}

Il semble que vous créez une instance de l'interface Rannable, mais que vous créez en fait une instance d'une classe anonyme qui implémente l'interface Rannable. Enfin, regardons l'expression lambda.

  1. Type Lambda

Dans la classe anonyme, "new Runnable () {}" et "public void run" sont omis pour créer une expression lambda.

public static void main(String[] args) {

  Runnable runner = () -> { System.out.println("Hello Lambda!"); };
  runner.run(); //Hello Lambda!
}

Le premier () représente l'argument de la méthode run, et le contenu de-> {} est le contenu de l'implémentation de la méthode run. La variable runner se voit attribuer une instance d'une classe anonyme qui implémente Runnable. En d'autres termes, une expression lambda est une expression qui crée une instance qui implémente l'interface.

Au fait, si j'omets "new Runnable () {}", je ne sais pas quel type d'instance créer. Java dispose d'un mécanisme pour déduire automatiquement en fonction du type de variable à affecter. Ce mécanisme est appelé inférence de type.

De plus, si vous omettez "public void run", vous ne saurez pas quelle méthode remplacer pour une interface qui a plusieurs méthodes définies. Par conséquent, les expressions lambda ne peuvent utiliser des interfaces qu'avec une seule méthode abstraite.

L'interface Rannable seule ne peut créer que des expressions lambda sans arguments et sans valeur de retour. Si vous souhaitez le créer sous une autre forme, une interface fonctionnelle a été ajoutée, alors utilisez-la.

Interface fonctionnelle

Une interface fonctionnelle est une interface qui peut être affectée à des expressions lambda et des références de méthode.

La condition d'une interface fonctionnelle est, grosso modo, une interface qui n'a qu'une seule méthode abstraite définie. Les méthodes statiques et les méthodes par défaut peuvent être incluses (ignorées comme condition de l'interface fonctionnelle). De plus, si une méthode publique de la classe Object est définie comme méthode abstraite dans l'interface, cette méthode est également ignorée. (Une interface qui satisfait à cette condition est désormais appelée "interface fonctionnelle" dans JDK1.8)

De nombreuses nouvelles interfaces ont été ajoutées sous le package java.util.function de SE8. https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/package-summary.html

Cette fois, je présenterai les interfaces les plus fréquemment utilisées.

2-1. Function<T, R> Function est une interface fonctionnelle pour la conversion des valeurs. Dans Function \ <T, R>, T spécifie le type de l'argument de la méthode et R spécifie le type de la valeur de retour. Prend un argument, le convertit (le calcule) et renvoie une autre valeur. La méthode est R appliquer (T).

Function<Integer, String> asterisker = (i) -> { return "*"+ i; };
String result = asterisker.apply(10);
System.out.println(result); // *10

2-2. Consumer<T> Consumer est une interface fonctionnelle pour recevoir des arguments et les utiliser pour le traitement. T dans Consumer \ spécifie le type d'argument de méthode. Comme il ne renvoie pas de valeur, il est essentiellement utilisé dans le but de provoquer des effets secondaires. La méthode est nulle accept (T).

Consumer<String> buyer = (goods) -> { System.out.println(goods + "j'ai acheté"); };
buyer.accept("balle de riz"); // balle de rizを購入しました。

2-3. Predicate<T> Predicate est une interface fonctionnelle pour faire des jugements. T dans Predicate \ spécifie le type d'argument de méthode. Reçoit un argument, rend un jugement et renvoie une valeur booléenne (résultat du jugement). La méthode est le test booléen (T).

Predicate<String> checker = (s)-> { return s.equals("Java"); };
boolean result = checker.test("Java");
System.out.println(result); //true

Intention d'utiliser l'expression lambda

Le code suivant décrit l'API Stream à l'aide d'expressions lambda.

List<Integer> numbers = List.of(3, 1, -4, 1, -5, 9, -2, 6, 5, 3, 5);
numbers.stream()
        .filter(number -> Math.abs(number) >= 5)
        .forEach(System.out::println);

Le résultat de sortie est le suivant.

-5
9
6
5
5

Ensuite, regardons le code écrit sans utiliser l'expression lambda.

List<Integer> numbers = List.of(3, 1, -4, 1, -5, 9, -2, 6, 5, 3, 5);

numbers.stream()
        .filter(new Predicate<Integer>() {
            @Override
            public boolean test(Integer number) {
                return Math.abs(number) >= 5;
            }
        })
        .forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer number) {
                System.out.println(number);
            }
        });

Comme introduit dans la décomposition de l'expression lambda, le nombre de descriptions de méthodes pour créer et exécuter des interfaces augmente. La quantité de code écrit a augmenté et les perspectives de traitement sont devenues très mauvaises. De cette manière, il est utilisé pour rendre la description de traitement concise et facile à comprendre.

Grammaire lambda

Explique la grammaire des expressions lambda. Voici la grammaire de base de l'expression lambda.

(argument) -> {En traitement; }

Ce qui suit est écrit selon cette grammaire.

// (1)S'il y a des arguments et des valeurs de retour
(Integer number) -> {
    return Math.abs(number) >= 5;
}

// (2)S'il n'y a pas de valeur de retour
(Integer number) -> {
    System.out.println(number);
}

// (3)S'il n'y a pas d'arguments ou de valeurs de retour
() -> {
    System.out.println("Hello!");
}

(1) est un exemple d'avoir un argument et une valeur de retour comme Predicate. Le traitement est effectué à l'aide du nombre spécifié par l'argument et la valeur de retour est renvoyée. (2) est un exemple sans valeur de retour comme Consumer. Dans ce cas, il n'est pas nécessaire d'écrire une instruction return. Pour le traitement sans arguments, comme dans (3), décrivez la partie argument dans (). Par exemple, java.lang.Runnable.

De plus, dans les expressions lambda, le type d'argument peut être omis. Et vous ne pouvez omettre les parenthèses () autour de l'argument que si vous n'avez qu'un seul argument. Il ne peut pas être omis s'il n'y a pas d'argument ou s'il y en a deux ou plus. L'application de cette règle à (1) et (3) donne:

// (1)Parce qu'il n'y a qu'un seul argument( )Peut être omis
number -> {
    return Math.abs(number) >= 5;
}

// (3)Parce qu'il n'y a pas d'argument( )Ne peut pas être omis
() -> {
    System.out.println("Hello!");
}

De plus, s'il n'y a qu'une seule ligne à traiter, vous pouvez omettre le crochet du milieu {}, le retour et le point-virgule à la fin de la phrase. Les abréviations de (1) à (3) sont les suivantes.

// (1)S'il y a des arguments et des valeurs de retour
number -> Math.abs(number) >= 5

// (2)S'il n'y a pas de valeur de retour
number -> System.out.println(number)

// (3)S'il n'y a pas d'arguments ou de valeurs de retour
() -> System.out.println("Hello!")

Enfin, l'argument lui-même peut être omis en utilisant la référence de méthode uniquement lorsque le contenu du traitement est un appel de méthode et que l'argument est déterminé de manière unique. La référence de méthode a la syntaxe suivante.

nom de la classe::Nom de la méthode

Cette référence de méthode ne peut être appliquée que dans (2). Si (2) est décrit à l'aide de la référence de méthode, ce sera comme suit.

System.out::println

La méthode System.out.println est une méthode qui ne prend qu'un seul argument, et il est clair que la valeur de l'argument Integer est passée, donc une référence de méthode est disponible. D'un autre côté, dans (1), la référence de méthode ne peut pas être utilisée car il y a un jugement de grandeur> = 5 après l'appel de méthode. De plus, dans (3), puisque la valeur "Hello!" Est spécifiée pour l'argument, on ne peut pas dire que l'argument est déterminé de manière unique, et la référence de méthode ne peut pas non plus être utilisée pour cela.

Dans cet esprit, jetons un coup d'œil au traitement du flux plus tôt.

List<Integer> numbers = List.of(3, 1, -4, 1, -5, 9, -2, 6, 5, 3, 5);
numbers.stream()
        .filter(number -> Math.abs(number) >= 5)
        .forEach(System.out::println);

Vous pouvez voir que les expressions lambda apprises en (1) et (2) sont incorporées dans streamAPI.

Article de référence

Comprendre les expressions Lambda Java 8 Java moderne appris avec les expressions Lambda et les API de flux - Le présent du langage Java qui change en incorporant des types de fonctions

Recommended Posts

J'ai essayé de résumer les expressions Java lambda
J'ai essayé de résumer l'apprentissage Java (1)
J'ai essayé de résumer Java 8 maintenant
[Java] Introduction à l'expression lambda
[Introduction à Java] À propos des expressions lambda
J'ai essayé de résumer le support d'iOS 14
J'ai essayé d'interagir avec Java
Comment utiliser les expressions Java lambda
J'ai essayé de résumer les bases de kotlin et java
J'ai essayé de résumer les méthodes utilisées
J'ai essayé de résumer l'API Stream
Qu'est-ce que Docker? J'ai essayé de résumer
J'ai essayé de résumer les méthodes de Java String et StringBuilder
Comprendre les expressions lambda Java 8
À propos des expressions Java lambda
Expliquer les expressions lambda Java 8
J'ai essayé de résumer sur JVM / garbage collection
J'ai essayé de faire une authentification de base avec Java
[Java] Résumé de la façon d'omettre les expressions lambda
java j'ai essayé de casser un simple bloc
J'ai essayé de sortir quatre-vingt-dix-neuf en Java
J'ai essayé de créer une compétence Alexa avec Java
J'ai essayé de casser le bloc avec java (1)
[Introduction à Java] J'ai essayé de résumer les connaissances que j'estime essentielles
J'ai essayé d'implémenter TCP / IP + BIO avec JAVA
J'ai essayé d'implémenter la notification push Firebase en Java
[Java 11] J'ai essayé d'exécuter Java sans compiler avec javac
[Java Silver] Résumé des points liés aux expressions lambda
[Java] J'ai essayé de résoudre le problème de rang B de Paiza
J'ai essayé de faire fonctionner SQS en utilisant AWS Java SDK
# 2 [Note] J'ai essayé de calculer quatre-vingt-dix-neuf avec Java.
J'ai essayé le type d'entrée / sortie de Java Lambda ~ Stream version ~
J'ai essayé de créer une compétence Clova en Java
J'ai essayé Drools (Java, InputStream)
J'ai essayé de créer une fonction de connexion avec Java
J'ai essayé de résumer divers link_to utilisés cette fois
J'ai essayé d'implémenter Sterling Sort avec Java Collector
J'ai essayé d'utiliser Java REPL
[Java] J'ai essayé de mettre en œuvre la recherche de produits de l'API Yahoo
J'ai essayé de vérifier yum-cron
J'ai essayé d'implémenter la méthode de division mutuelle d'Eugrid en Java
~ J'ai essayé d'apprendre la programmation fonctionnelle avec Java maintenant ~
J'ai essayé la métaprogrammation avec Java
J'ai essayé de découvrir ce qui avait changé dans Java 9
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
J'ai essayé de moderniser une application Java EE avec OpenShift.
[JDBC] J'ai essayé d'accéder à la base de données SQLite3 depuis Java.
J'ai essayé de faire coexister Java Optional et la clause de garde
J'ai brièvement résumé la grammaire de base de Ruby
J'ai essayé de résumer les applications et les outils de développement personnellement utiles (outils de développement)
J'ai essayé de convertir une chaîne de caractères en un type LocalDate en Java
J'ai essayé de résumer les applications et les outils de développement personnellement utiles (Apps)
J'ai essayé d'utiliser Dapr en Java pour faciliter le développement de microservices
J'ai créé un client RESAS-API en Java
J'ai essayé de résumer l'orientation de l'objet à ma manière.
Expression lambda Java apprise avec Comparator
J'ai essayé de mâcher C # (indexeur)
J'ai essayé la communication UDP avec Java