Les expressions lambda ont-elles une utilité autre que l'enregistrement de lignes de code?
Existe-t-il des fonctionnalités spéciales fournies par lambdas qui résolvaient des problèmes qui n'étaient pas faciles à résoudre? L'utilisation typique que j'ai vue est qu'au lieu d'écrire ceci:
Comparator<Developer> byName = new Comparator<Developer>() {
@Override
public int compare(Developer o1, Developer o2) {
return o1.getName().compareTo(o2.getName());
}
};
Nous pouvons utiliser une expression lambda pour raccourcir le code:
Comparator<Developer> byName =
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName());
(o1, o2) -> o1.getName().compareTo(o2.getName())
Comparator.comparing(Developer::getName)
Réponses:
Les expressions Lambda ne changent pas l'ensemble des problèmes que vous pouvez résoudre avec Java en général, mais facilitent certainement la résolution de certains problèmes, juste pour la même raison que nous ne programmons plus en langage assembleur. La suppression des tâches redondantes du travail du programmeur facilite la vie et permet de faire des choses que vous ne toucheriez même pas autrement, juste pour la quantité de code que vous auriez à produire (manuellement).
Mais les expressions lambda ne sont pas seulement de sauver des lignes de code. Les expressions Lambda vous permettent de définir des fonctions , ce pour quoi vous pouvez auparavant utiliser des classes internes anonymes comme solution de contournement, c'est pourquoi vous pouvez remplacer les classes internes anonymes dans ces cas, mais pas en général.
Plus particulièrement, les expressions lambda sont définies indépendamment de l'interface fonctionnelle vers laquelle elles seront converties, il n'y a donc pas de membres hérités auxquels ils pourraient accéder, de plus, elles ne peuvent pas accéder à l'instance du type implémentant l'interface fonctionnelle. Dans une expression lambda,
this
etsuper
ont la même signification que dans le contexte environnant, voir aussi cette réponse . De plus, vous ne pouvez pas créer de nouvelles variables locales occultant les variables locales du contexte environnant. Pour la tâche prévue de définir une fonction, cela supprime un grand nombre de sources d'erreur, mais cela implique également que pour d'autres cas d'utilisation, il peut y avoir des classes internes anonymes qui ne peuvent pas être converties en une expression lambda, même si vous implémentez une interface fonctionnelle.De plus, la construction
new Type() { … }
garantit de produire une nouvelle instance distincte (commenew
toujours). Les instances de classe interne anonymes conservent toujours une référence à leur instance externe si elles sont créées dans un non-static
contexte. En revanche, les expressions lambda capturent une référence uniquementthis
lorsque cela est nécessaire, c'est-à-dire si elles y accèdentthis
ou si elles ne sont passtatic
membres. Et ils produisent des instances d'une identité intentionnellement non spécifiée, ce qui permet à l'implémentation de décider au moment de l'exécution s'il faut réutiliser les instances existantes (voir aussi « Une expression lambda crée-t-elle un objet sur le tas à chaque exécution? »).Ces différences s'appliquent à votre exemple. Votre construction de classe interne anonyme produira toujours une nouvelle instance, elle peut également capturer une référence à l'instance externe, tandis que votre
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName())
est une expression lambda non capturante qui évaluera à un singleton dans les implémentations typiques. De plus, il ne produit pas de.class
fichier sur votre disque dur.Compte tenu des différences concernant à la fois la sémantique et les performances, les expressions lambda peuvent changer la façon dont les programmeurs résoudront certains problèmes à l'avenir, bien sûr, également en raison des nouvelles API englobant des idées de programmation fonctionnelle utilisant les nouvelles fonctionnalités du langage. Voir aussi Expression lambda Java 8 et valeurs de première classe .
la source
Les langages de programmation ne sont pas destinés aux machines à exécuter.
Ils sont pour les programmeurs de penser à.
Les langages sont une conversation avec un compilateur pour transformer nos pensées en quelque chose qu'une machine peut exécuter. L' une des principales plaintes au sujet de Java de personnes qui viennent des autres langues (ou quittent ce pour d' autres langues) utilisées pour être qu'il force un modèle mental sur le programmeur (c. -à- tout est une classe).
Je ne vais pas me demander si c'est bon ou mauvais: tout est compromis. Mais les lambdas Java 8 permettent aux programmeurs de penser en termes de fonctions , ce que vous ne pouviez pas faire auparavant en Java.
C'est la même chose qu'un programmeur procédural apprenant à penser en termes de classes quand ils arrivent à Java: vous les voyez passer progressivement de classes qui sont des structures glorifiées et ont des classes `` d'assistance '' avec un tas de méthodes statiques et passer à quelque chose qui ressemble plus à une conception rationnelle OO (mea culpa).
Si vous les considérez simplement comme un moyen plus court d'exprimer des classes internes anonymes, vous ne les trouverez probablement pas très impressionnants de la même manière que le programmeur procédural ci-dessus ne pensait probablement pas que les classes étaient une grande amélioration.
la source
L'enregistrement de lignes de code peut être considéré comme une nouvelle fonctionnalité, si cela vous permet d'écrire une partie substantielle de la logique d'une manière plus courte et plus claire, ce qui prend moins de temps pour que les autres le lisent et la comprennent.
Sans expressions lambda (et / ou références de méthode), les
Stream
pipelines auraient été beaucoup moins lisibles.Pensez, par exemple, à quoi
Stream
aurait ressemblé le pipeline suivant si vous remplaçiez chaque expression lambda par une instance de classe anonyme.Ce serait:
C'est beaucoup plus difficile à écrire que la version avec des expressions lambda, et c'est beaucoup plus sujet aux erreurs. C'est aussi plus difficile à comprendre.
Et c'est un pipeline relativement court.
Pour rendre cela lisible sans expressions lambda et références de méthode, vous auriez dû définir des variables contenant les diverses instances d'interface fonctionnelle utilisées ici, ce qui aurait divisé la logique du pipeline, ce qui le rendrait plus difficile à comprendre.
la source
Comparator
forsorted
car il compare de toute façon dans l'ordre naturel. Peut-être le changer pour comparer la longueur des chaînes ou similaire, pour rendre l'exemple encore meilleur?compareToIgnoreCase
pour qu'il se comporte différemment desorted()
.compareToIgnoreCase
est encore un mauvais exemple, car vous pourriez simplement utiliser leString.CASE_INSENSITIVE_ORDER
comparateur existant . La suggestion de @ tobias_k de comparer par longueur (ou toute autre propriété n'ayant pas de comparateur intégré) convient mieux. À en juger par des exemples de code SO Q&A, les lambdas ont causé beaucoup d'implémentations de comparateurs inutiles…Itération interne
Lors de l'itération des collections Java, la plupart des développeurs ont tendance à obtenir un élément puis à le traiter . C'est à dire, retirez cet élément puis utilisez-le, ou réinsérez-le, etc. Avec les versions antérieures à 8 de Java, vous pouvez implémenter une classe interne et faire quelque chose comme:
Maintenant, avec Java 8, vous pouvez faire mieux et moins verbeux avec:
ou mieux
Les comportements comme arguments
Devinez le cas suivant:
Avec l' interface Java 8 Predicate, vous pouvez faire mieux comme ceci:
En l'appelant comme:
Source: DZone - Pourquoi nous avons besoin d'expressions Lambda en Java
la source
numbers.forEach((Integer value) -> System.out.println(value));
l'expression lambda est composée de deux parties, l'une à gauche du symbole fléché (->) listant ses paramètres et celle de droite contenant son corps . Le compilateur détecte automatiquement que l'expression lambda a la même signature de la seule méthode non implémentée de l'interface Consumer.Il y a de nombreux avantages à utiliser des lambdas au lieu de la classe interne comme ci-dessous:
Rendre le code plus compact et expressif sans introduire plus de sémantique de syntaxe de langage. vous avez déjà donné un exemple dans votre question.
En utilisant des lambdas, vous êtes heureux de programmer avec des opérations de style fonctionnel sur des flux d'éléments, telles que des transformations de réduction de carte sur des collections. voir la documentation des packages java.util.function et java.util.stream .
Il n'y a pas de fichier de classes physiques généré pour les lambdas par le compilateur. Ainsi, cela rend vos applications livrées plus petites. Comment la mémoire affecte-t-elle lambda?
Le compilateur optimisera la création lambda si le lambda n'accède pas aux variables hors de sa portée, ce qui signifie que l'instance lambda ne sera créée qu'une seule fois par la JVM. pour plus de détails, vous pouvez voir la réponse de @ Holger à la question La mise en cache de référence de méthode est-elle une bonne idée dans Java 8? .
Lambdas peut implémenter plusieurs interfaces de marqueurs en plus de l'interface fonctionnelle, mais les classes internes anonymes ne peuvent pas implémenter plus d'interfaces, par exemple:
la source
Les lambdas ne sont que du sucre syntaxique pour les classes anonymes.
Avant les lambdas, les classes anonymes peuvent être utilisées pour réaliser la même chose. Chaque expression lambda peut être convertie en une classe anonyme.
Si vous utilisez IntelliJ IDEA, il peut effectuer la conversion pour vous:
la source
Pour répondre à votre question, le fait est que les lambdas ne vous permettent pas de faire quoi que ce soit que vous ne pouviez pas faire avant java-8, mais plutôt d'écrire du code plus concis . L'avantage de cela, c'est que votre code sera plus clair et plus flexible.
la source
Une chose que je ne vois pas encore mentionnée est qu'un lambda vous permet de définir les fonctionnalités là où il est utilisé .
Donc, si vous avez une fonction de sélection simple, vous n'avez pas besoin de la mettre dans un endroit séparé avec un tas de passe-partout, vous écrivez simplement un lambda qui est concis et localement pertinent.
la source
Oui, de nombreux avantages sont là.
la source