J'ai récemment maîtrisé l'expression Lambda introduite dans Java 8. Je trouve que chaque fois que j'utilise une interface fonctionnelle, j'ai tendance à toujours utiliser une expression Lambda au lieu de créer une classe qui implémente le interface fonctionnelle.
Est-ce considéré comme une bonne pratique? Ou sont leurs situations où l'utilisation d'un Lambda pour une interface fonctionnelle n'est pas appropriée?
Il existe un certain nombre de critères qui devraient vous inciter à ne pas utiliser de lambda:
priceIsOver100
. x -> x.price > 100
est aussi clair que ce nom. Je veux dire des noms comme isEligibleVoter
qui remplacent une longue liste de conditions.N'allez pas trop loin. N'oubliez pas que le logiciel peut facilement être modifié. En cas de doute, écrivez-le dans les deux sens et voyez ce qui est plus facile à lire.
Ça dépend. Chaque fois que vous vous retrouvez à utiliser le même lambda à différents endroits, vous devriez envisager d'implémenter une classe qui implémente l'interface. Mais si vous auriez utilisé une classe interne anonyme sinon je pense qu'un lambda est bien mieux.
Je soutiens la réponse de Karl Bielefeldt, mais je souhaite apporter un bref ajout.
La réponse acceptée Réponse de Karl Bielefeldt est correcte. Je peux ajouter une autre distinction:
Le code lambda imbriqué dans une méthode à l'intérieur d'une classe peut accéder à toutes les variables - final trouvées dans cette méthode et cette classe.
La création d'une classe qui implémente l'interface fonctionnelle ne vous donne pas un tel accès direct à l'état du code appelant.
Pour citez le Java (le mien est souligné):
Comme les classes locales et anonymes, les expressions lambda peuvent capturer des variables; ils ont le même accès aux variables locales de la portée englobante . Cependant, contrairement aux classes locales et anonymes, les expressions lambda ne présentent aucun problème de duplication (voir la section Observation pour plus d'informations). Les expressions lambda ont une portée lexicale. Cela signifie qu'ils n'héritent d'aucun nom d'un sur-type ni n'introduisent un nouveau niveau de portée. Les déclarations dans une expression lambda sont interprétées comme elles le sont dans l'environnement englobant.
Ainsi, bien qu'il soit avantageux d'extraire un code long et de le nommer, vous devez le comparer à la simplicité de l'accès direct à l'état de la méthode et de la classe qui les entourent.
Voir:
Cela pourrait être un choix compliqué, mais à tous les autres excellents points soulevés dans d'autres réponses, j'ajouterais:
Préférer les références de méthode si possible. Comparer:
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);
versus
employees.stream()
.map(employee -> employee.getName())
.forEach(employeeName -> System.out.println(employeeName));
L'utilisation d'une référence de méthode vous évite d'avoir à nommer les arguments de lambda, qui sont généralement redondants et/ou conduisent à des noms paresseux comme e
ou x
.
En s'appuyant sur la réponse de Matt McHenry, il peut y avoir une relation entre lambda et les références de méthode où le lambda peut être réécrit sous la forme d'une série de références de méthode. Par exemple:
employees.stream()
.forEach(employeeName -> System.out.println(employee.getName()));
contre
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);