Comprendre comment la programmation fonctionnelle a été introduite dans Java d'un seul coup

introduction

J'ai Java SE8 Gold, et maintenant je peux utiliser l'interface fonctionnelle, l'expression lambda et l'API Stream qui ont occupé la plupart des questions, mais qu'est-ce que c'est après tout? C'était dans un état.

Par conséquent, j'ai décidé de résumer pourquoi la programmation fonctionnelle a été introduite en premier lieu et comment est née l'idée d'interfaces fonctionnelles et d'expressions lambda. (~~ Résumez avant de passer l'examen ~~)

Programmation pédagogique et programmation fonctionnelle

Java a approuvé la programmation pédagogique!

Tout à coup, jetez un œil au code ci-dessous.

  public static void findMatsumoto(List<String> names) {

    boolean found = false;

    for (String name : names) {
      if (name.equals("Matsumoto")) {
        found = true;
        break;
      }
    }
     
    if (found)
      System.out.println("Found Matsumoto");
    else
      System.out.println("Sorry, Matsumoto not found");
  }

C'est une méthode très simple. La liste de noms passée en argument est bouclée élément par élément pour vérifier si elle correspond à Matsumoto. S'il y a un élément qui correspond à Matsumoto, définissez la variable locale trouvée préparée à l'avance sur true et quittez la boucle. Enfin, si trouvé est vrai, "found Matsumoto" est affiché, et si trouvé est faux, "Désolé, Matsumoto introuvable" est affiché.

Comme mentionné ci-dessus, cette méthode est écrite dans ce que l'on appelle la "** programmation pédagogique **" qui définit toutes les étapes de répétition de chaque élément, de comparaison des valeurs, de définition des indicateurs et de sortie de la boucle. Je vais.

Que se passe-t-il si vous essayez d'écrire en programmation fonctionnelle?

Si vous essayez de décrire la méthode de ↑ par programmation fonctionnelle, ce sera comme suit.

public static void findMatsumoto(List<String> names) {

  if (names.contains("Matsumoto"))
    System.out.println("Found Matsumoto");
  else
    System.out.println("Sorry, Matsumoto not found");

}

C'est beaucoup plus propre que la programmation pédagogique, n'est-ce pas? En particulier, le type de fonction ne décrit pas le traitement en boucle. La méthode contains s'occupe de tout, et le développeur n'a rien à voir avec la façon dont c'est fait. Cependant, vous pouvez obtenir le résultat attendu avec juste cette description.

En d'autres termes, l'écriture en programmation fonctionnelle peut aboutir à un ** code concis et facile à comprendre ** par rapport à la programmation impérative.

★ Références [1] [Raccourci vers la transition vers la programmation fonctionnelle - Introduction de méthodes fonctionnelles dans les programmes Java avec une façon de penser déclarative-](https://www.ibm.com/developerworks/jp/java/library/j- java8idioms1 / index.html)

Il existe de nombreux autres avantages de la programmation fonctionnelle!

En plus de rendre le code concis et facile à comprendre, la programmation fonctionnelle présente de nombreux avantages.

En programmation fonctionnelle, les fonctions ont les propriétés suivantes. ** ● Renvoie toujours le même résultat pour la valeur saisie ** ** ● L'évaluation des fonctions n'a aucun effet sur les autres **

Les méthodes suivantes peuvent être appelées des fonctions.

public int add(int x, int y) {

  return x + y;

}

Il renvoie toujours le même résultat pour les entrées (x et y), et l'évaluation ici n'a pas d'autre effet.

D'autre part, les méthodes suivantes peuvent-elles être appelées fonctions?

public int add(int y) {

  return x += y; //x est une variable définie en dehors de la méthode

}

Cette méthode ne renvoie pas toujours le même résultat pour l'entrée y. (Dépend de la variable externe x.) Il affecte également la variable externe x. D'après ce qui précède, cette méthode ne peut pas être appelée une fonction.

En raison des propriétés ci-dessus, les avantages suivants peuvent être pris en compte en utilisant la fonction. ** 1. Facile à tester ** Vous n'avez besoin de considérer qu'un seul scénario de test, car le même résultat sera toujours renvoyé pour la valeur que vous entrez.

** 2. Hautement sûr ** Comme l'évaluation par la fonction n'a aucune influence sur les autres, elle est très sûre sans changements inattendus.

** 3. Rationalisez le traitement parallèle ** Il convient au traitement parallèle car les fonctions ne dépendent pas les unes des autres. Ces dernières années, l'amélioration des performances d'un seul cœur s'est ralentie et l'architecture du processeur a tendance à être multicœur avec plus de cœurs. On s'attend à ce que l'utilisation des fonctions corresponde à cette tendance vers le multicœur. En d'autres termes, il est possible d'améliorer l'efficacité du traitement parallèle et d'améliorer la vitesse de traitement.

Propriétés notables de la programmation fonctionnelle

De plus, il existe deux propriétés notables de la programmation fonctionnelle: ** ● Vous pouvez passer une fonction comme argument d'une fonction ** ** ● Vous pouvez transmettre la fonction comme valeur de retour de la fonction **

Je voudrais montrer un exemple concret utilisant "** Haskell **" qui est célèbre comme langage de programmation fonctionnel.

Ce qui suit est un programme qui génère la valeur totale des éléments du tableau.

haskell


ary = [ 1, 3, 5, 7, 9 ]
main = print $ foldl (+) 0 ary

La fonction (+) est passée comme premier argument d'une fonction appelée foldl. Renvoie la valeur totale des éléments du tableau ary passé dans le 3ème argument, avec 0 comme valeur initiale dans le 2ème argument. Vous pouvez voir qu'il est écrit de manière très concise.

Si vous essayez de faire la même chose en Java,

Java



public static int addAll(int[] ary) {

    int total = 0;

    for (int i : ary) {
        total += i;
    }

    return total;
}

public static void main(String[] args) {
    int[] ary = { 1, 3, 5, 7, 9 };
    System.out.println(addAll(ary));
}

Ce sera. J'écris un processus en boucle, donc le code est un peu long.

Si vous utilisez la programmation fonctionnelle, vous pouvez décrire le processus d'affichage des éléments d'un tableau sur la console en ** une seule ligne **, de sorte que la différence dans la quantité de description est évidente.

****** Jusqu'à présent, je n'ai couvert que les avantages de la programmation fonctionnelle, mais je ne pense pas aveuglément que la programmation fonctionnelle est la meilleure !!! ** Pour clarifier le contexte ** Seules les prestations sont prises en compte. La supériorité et l'infériorité de la programmation fonctionnelle, de la programmation pédagogique et de la programmation procédurale sortent du cadre de cet article et ne seront pas discutées. (Parfois, je ne suis pas si familier avec la programmation fonctionnelle que je peux en discuter moi-même.)

★ Références [2] Allons-y avec la programmation fonctionnelle ~ L'entrée de l'entrée fonctionnelle que tout le monde aime de Java [3] Connaissons la puissance de la programmation fonctionnelle - Partie 2

S'il y a tant d'avantages, vous devriez introduire la programmation fonctionnelle même en Java!

Je l'ai écrit depuis longtemps jusqu'à présent, mais pour résumer brièvement, la programmation fonctionnelle présente de nombreux avantages, et introduisons-la à Java! C'est devenu. Cependant, bien que cela ait de grands mérites, ce n'était pas simple en raison des défis.

Problèmes d'incorporation de l'essence de la programmation fonctionnelle dans Java

Notez que, comme vous pouvez le voir d'après la nature des fonctions en programmation fonctionnelle, "Vous pouvez passer une fonction à l'argument d'une fonction", "fonction en programmation fonctionnelle" = "méthode".

Pour élaborer un peu plus, la programmation fonctionnelle traite une fonction comme un objet de première classe, vous pouvez donc passer une fonction en tant qu'argument de fonction, mais comme un objet de première classe en Java est une classe, ** une méthode est utilisée comme argument de méthode. Il ne peut pas être adopté **.

Présentation de "Interface fonctionnelle"

Comme mentionné précédemment, Java ne vous permet pas de transmettre une méthode en tant qu'argument de méthode. Cependant, s'il s'agit d'un objet (instance), vous pouvez le passer en argument!

Alors, j'ai créé un ** objet de type fonction ! Ensuite, " interface fonctionnelle **" a été conçue.

Qu'est-ce qu'une interface fonctionnelle?

C'est une "interface fonctionnelle" créée comme un objet de type fonction, mais sa définition est la suivante.

** ● Interface avec une seule méthode abstraite (interface SAM) **

Exemple spécifique d'interface fonctionnelle

@FunctionalInterface
public interface Example {
    public int calc(int x);      //Méthode abstraite (SAM)
    static void say() { }        //méthode statique
    default void hello() { }     //méthode par défaut
    public String toString();    //Méthode publique de la classe Object
}

Ceci est une interface fonctionnelle!



** e? ** **

Où est-ce une fonction? Je pense que j'ai ressenti cela. Eh bien, c'est compréhensible en l'utilisant, alors écrivons un programme.

Lorsque vous passez un objet fonction (interface de type de fonction) comme argument d'une méthode, utilisez la notation "** classe interne anonyme **". Pour plus d'informations sur les classes internes anonymes, veuillez vous référer à la littérature [4].

//Interface fonctionnelle
@FunctionalInterface
public interface Calc {
    public int add(int x, int y);    //Méthode abstraite (SAM)
}

//Implémentation de la méthode d'impression avec Calc comme argument
private void print(int x, int y, Calc c) {
    System.out.println(c.add(x, y));
}

//Appelez la méthode d'impression
print(3, 4, new Calc() {
    @Override
    public int add(int x, int y) {
        return x + y;
    }
});

//Résultat d'exécution 7

Comme décrit ci-dessus, en utilisant la classe interne anonyme, il est possible d'instancier l'interface fonctionnelle Calc, d'implémenter la méthode abstraite add et de la transmettre à l'argument de la méthode d'impression.



** e? ** **

La quantité de description n'est pas du tout petite et cela ne ressemble pas à une programmation fonctionnelle! !!

C'est vrai. C'est là que le "** style Lambda **" entre en jeu.

★ Références [4] Classe intérieure anonyme [5] Introduction à Java8 Lambda [6] Interfaces fonctionnelles - Apprenez à créer des interfaces fonctionnelles personnalisées et pourquoi vous devriez toujours utiliser des interfaces fonctionnelles intégrées lorsque cela est possible- /java/library/j-java8idioms7/index.html)

Quand je l'écris dans le style lambda ...

Qu'est-ce qu'un type lambda?

Une expression lambda est une notation qui simplifie l'instanciation d'une classe qui implémente une méthode abstraite d'une interface fonctionnelle (ce qui a été fait plus tôt dans la classe interne anonyme).

Voyons comment l'omettre concrètement. (1) Premièrement, il est évident d'après l'inférence de type du compilateur que le type de la variable qui peut être passé au troisième argument de la méthode d'impression est un objet de type Calc, donc "new Calc () {}" peut être omis.

(2) De plus, puisque l'interface Calc est une interface fonctionnelle, puisqu'il n'y a qu'une seule méthode abstraite, il est évident de la surcharger et de l'implémenter, donc "@ Override public int add" peut également être omis.

(3) Enfin, le type d'argument est également évident par inférence de type, il peut donc être omis, et si le bloc de méthode ({}) est omis, le mot-clé return peut également être omis (dans ce cas, return ne peut pas être décrit plutôt que omis). Sur la base de ce qui précède, l'appel ci-dessus à la méthode d'impression peut être réécrit comme suit.

//Appelez la méthode d'impression
print(3, 4, (x, y) -> x + y);

Oh, c'est vraiment court! Ce que nous faisons est le même que pour la classe interne anonyme, nous implémentons la méthode add add pour instancier la classe, mais la description du nouvel opérateur et des substitutions de méthode qui sont normalement requises pour l'instanciation est C'est abrégé, donc c'est très concis, et il semble que vous passiez une ** fonction (méthode) qui fait l'ajout directement à l'argument de la méthode **.

C'est vrai! !! En d'autres termes, ** le code écrit simplifié à l'aide d'expressions lambda ressemble à de la programmation fonctionnelle **!

Maîtrisez la formule lambda

Vous avez découvert que vous pouvez introduire la programmation fonctionnelle en utilisant une combinaison d'interfaces fonctionnelles et d'expressions lambda.

Et le package java.util.function de Java8 fournit une interface de type fonction à usage général, et le package java.util.stream est une API pour le traitement des données dans un format de pipeline, avec une interface de type fonction comme argument. Il existe de nombreuses méthodes à adopter. Bien sûr, vous pouvez également créer une interface fonctionnelle personnalisée.

Le programme suivant affiche les noms des hommes dans la liste des noms.

names.stream().filter(n -> n.getSex() == 0)
    .map(n -> n.getName())
    .forEach(System.out::println);

N'est-ce pas facile à lire et concis? De cette manière, une bonne combinaison d'interfaces fonctionnelles et d'expressions lambda, d'interfaces fonctionnelles intégrées et d'API Stream peut introduire la programmation fonctionnelle.

Je voudrais résumer le package java.util.function et l'API Stream dans un article séparé.

★ Références [7] [Collecte des problèmes de Thorough Strategy Java SE 8 Gold](https://www.amazon.co.jp/ Thorough Strategy-Java-Gold-Problem Collection-1Z0-809 / dp / 4295000035 / ref = sr_1_2? S = livres & ie = UTF8 & qid = 1538986245 & sr = 1-2 & mots-clés = java + or + se8) [8] Comprendre les expressions Java 8 Lambda

Résumé

Comme la programmation fonctionnelle présente de nombreux avantages, j'aimerais également l'introduire dans Java.   ↓ En préparant un objet (interface fonctionnelle) qui n'a qu'une seule classe abstraite au lieu d'une fonction et en simplifiant l'instanciation de classe à l'aide d'expressions lambda, nous avons pu introduire la programmation fonctionnelle dans Java! !!

Recommended Posts

Comprendre comment la programmation fonctionnelle a été introduite dans Java d'un seul coup
~ J'ai essayé d'apprendre la programmation fonctionnelle avec Java maintenant ~
Comment maîtriser la programmation en 3 mois
Introduction à la programmation fonctionnelle (Java, Javascript)
Comment apprendre JAVA en 7 jours
Comment utiliser les classes en Java?
Comment nommer des variables en Java
Comment concaténer des chaînes avec Java
Comment incrémenter la valeur de Map sur une ligne en Java
Comment implémenter le calcul de la date en Java
Comment implémenter le filtre de Kalman par Java
Prise en charge multilingue de Java Comment utiliser les paramètres régionaux
Référence Java à comprendre dans la figure
Comment faire une conversion de base en Java
Comment appliquer les conventions de codage en Java
Comment intégrer Janus Graph dans Java
Comment obtenir la date avec Java
Comprendre en 5 minutes !! Comment utiliser Docker
Comment utiliser credentials.yml.enc introduit à partir de Rails 5.2
Comment afficher une page Web en Java
Comment obtenir une classe depuis Element en Java
Comment masquer les champs nuls en réponse en Java
Comment résoudre les problèmes d'expression en Java
Comment écrire Java String # getBytes dans Kotlin?
Réflexion: Comment utiliser une interface fonctionnelle pour vos propres fonctions (java)
Comment appeler des fonctions en bloc avec la réflexion Java
Comment créer un environnement Java en seulement 3 secondes
[Java] Comment omettre le constructeur privé dans Lombok
Comment entrer / sortir des fichiers mainframe IBM en Java?
Comprendre comment utiliser le décodeur JSON de Swift en 3 minutes
Comment créer un URI de données (base64) en Java
Classes et instances Java comprises dans la figure
Comment convertir A en A et A en A en utilisant le produit logique et la somme en Java
Comment convertir un fichier en tableau d'octets en Java
Comment Git gérer les projets Java EE dans Eclipse
Résumé de la mise en œuvre des arguments par défaut en Java
Comment mettre l'ancien Java (série 8) dans macOS 10.15 Catalina
Remarques sur l'utilisation des expressions régulières en Java
Comment initialiser par lots des tableaux avec Java que je ne savais pas quand j'étais débutant
Comment obtenir le nom d'une classe / méthode exécutée en Java
Comment lire votre propre fichier YAML (*****. Yml) en Java
Comment utiliser les données JSON dans la communication WebSocket (Java, JavaScript)
Mémo: [Java] Comment vérifier groupId etc. décrit dans pom.xml
Comment stocker des chaînes de ArrayList à String en Java (personnel)
Que s'est-il passé dans «Java 8 to Java 11» et comment créer un environnement
Comment appeler et utiliser l'API en Java (Spring Boot)
Comment utiliser le type d'énumération Java (Enum) dans Mapper XML de MyBatis
Comment changer dynamiquement les JDK lors de la construction de Java avec Gradle
Comment développer et enregistrer une application Sota en Java
Comment simuler le téléchargement de formulaires post-objet vers OSS en Java
Comment déployer une application Java sur Alibaba Cloud EDAS dans Eclipse
Comment dériver le dernier jour du mois en Java
Différences dans la gestion des chaînes entre Java et Perl
Une introduction aux types fonctionnels pour les programmeurs orientés objet dans Elm
Comment changer Java à l'ère d'OpenJDK sur Mac
Comment abaisser la version java
[Java] Comment utiliser Map
Comment désinstaller Java 8 (Mac)