29 votes

Quelle est la différence entre une interface prédicat et une interface fonction en Java8 ?

Je sais que c'est peut-être une question très basique sur le SO mais je veux savoir quelle est la différence entre un Predicate et un Function dans Java8 ?

Predicate<String> predicateTest  = (s)-> s.length() > 5;       
System.out.println(predicateTest.test("Predicate"));

Function<String, Boolean> functionTest = str -> str.length()> 5;      
System.out.println(functionTest.apply("Function"));

Ici, dans mon exemple, les deux reviennent true La seule chose est que la façon d'appeler est différente ?

4 votes

A Predicate est juste un Function qui renvoie Boolean . En d'autres termes Predicate<T> est un Function<T, Boolean> . Mais Predicate renvoie un boolean il n'y a donc pas de relation d'héritage.

4 votes

@BoristheSpider nitpick, c'est boolean no Boolean

0 votes

@Eugene, je mets juste les choses au point.

37voto

Aomine Points 42709

Différence entre Predicate<T> y Function<T, R>

Avant tout, un Predicate<T> es strictement une fonction à valeur booléenne :

         _ _ _ _ _ _ _ 
        |             |
  T --> |  predicate  | --> boolean
        |_ _ _ _ _ _ _|   

Alors que cela n'est pas nécessairement vrai pour un Function<T, R> :

         _ _ _ _ _ _ _ 
        |             |
  T --> |   function  | --> R
        |_ _ _ _ _ _ _| 

Ce dernier consomme n'importe quel type d'objet tout comme Predicate<T> permet mais peut varier dans le type de retour.

Cas d'utilisation de Predicate<T> y Function<T, R>

Le cas d'utilisation de Predicate<T> c'est lorsque vous avez besoin d'une fonction qui consomme un argument de type T et renvoie un booléen. Par exemple, cela peut être dans une situation où vous voulez filtrer un flux d'éléments, trouver le premier élément d'un flux qui satisfait à une condition comme telle de .filter(predicate).findFirst() ou la vérification de la présence d'un élément d'un flux qui satisfait à une certaine condition comme tel de anyMatch , noneMatch , allMatch etc.

Le cas d'utilisation de Function<T, R> c'est lorsque vous avez besoin d'une fonction qui consomme un argument de type T et le transforme en un type R Par exemple, cela peut être lors de l'appel stream.map(func) .

Explication de votre extrait de code :

En ce qui concerne l'extrait d'exemple dans votre post Predicate<String> y Function<String, Boolean> sont la même chose en termes de ce qu'ils représentent, c'est-à-dire qu'ils représentent tous les deux une fonction prenant a String et renvoyer un boolean . Cependant, la première évite de mettre en boîte la valeur renvoyée par la fonction boolean a Boolean alors que la seconde ne le fait pas.

Cela dit, cela ne signifie pas nécessairement que partout où l'on peut utiliser une Predicate<String> vous pouvez également utiliser un Function<String, Boolean> ou vice versa.

Exemple :

Pendant que ça se compile :

Predicate<String> predicate = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(predicate);

Ce n'est pas le cas :

Function<String, Boolean> function = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(function);

et vice versa :

Pendant que ça marche :

Function<String, Boolean> function = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(function);

Ce n'est pas le cas :

Predicate<String> predicate = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(predicate);

3 votes

Vous pouvez également mentionner que Predicate a des méthodes par défaut and() , or() y negate() qui ont un sens pour les conditions, alors que les méthodes par défaut sur Function ont plus de sens pour le filtrage/chaînage.

0 votes

@JensBannmann C'est un point important (pratique !). Bien plus pertinent que le charabia des autres réponses (qui, lorsqu'elles disent qu'il n'y a ~"pas de différence", ont tout simplement tort...). Envisagez d'ajouter ce point comme une réponse (appropriée !). Sinon, je ferais un essai...

1 votes

@JensBannmann Merci pour vos commentaires. Je ne suis pas en mesure d'intégrer cela dans ma réponse avant ce soir, mais n'hésitez pas à modifier la réponse et à l'améliorer si nécessaire. Sinon, si vous le souhaitez, vous pouvez également poster votre propre réponse comme le suggère Marco :)

7voto

Eugene Points 6271

Dans ce cas, il n'y a pas de différence, cela n'a d'importance que pour les choses auxquelles vous pouvez vous appliquer. Ainsi, par exemple allMatch s'attend à ce qu'un Predicate vous ne pouvez pas passer un Function même si, logiquement, ils font la même chose.

3 votes

Utilisation de myFunction::apply pourrait probablement fonctionner quand même

1 votes

@Lino right, it would, but that would be a little extra on the behalf of the user

2 votes

Bien que ce ne soit peut-être pas le bon endroit pour "discuter" de choses (et si vous le souhaitez, nous pouvons aller dans un chat). Mais au vu de vos commentaires sur les autres réponses, este peut au moins soulever la question de savoir pourquoi les différentes interfaces existent en premier lieu (et je pense que c'est une bonne question, avec quelques bizarreries techniques intéressantes). Pour ainsi dire, ils auraient pu omettre Predicate et je m'attendais juste à un Function<T, Boolean> dans des méthodes comme anyMatch . (En laissant le null pour l'instant).

5voto

Jens Bannmann Points 1148

La réponse d'Aominè couvre les différences fondamentales. J'aimerais ajouter que les deux interfaces ont également des méthodes par défaut spécialisées différentes, c'est-à-dire des méthodes que vous pouvez appeler sur toute classe d'implémentation :

  • Predicate<T>
    • Predicate<T> and(Predicate<? super T> other) - Renvoie un prédicat composé qui représente un ET logique de court-circuitage de ce prédicat et d'un autre.
    • Predicate<T> or(Predicate<? super T> other) - Renvoie un prédicat composé qui représente un OU logique court-circuitant de ce prédicat et d'un autre.
    • negate() - Renvoie un prédicat qui représente la négation logique de ce prédicat.
  • Function<T,R>
    • <V> Function<T,V> andThen(Function<? super R,? extends V> after) - Renvoie une fonction composée qui applique d'abord cette fonction à son entrée, puis applique la fonction after au résultat.
    • <V> Function<V,R> compose(Function<? super V,? extends T> before) - Retourne une fonction composée qui applique d'abord le before à son entrée, puis applique cette fonction au résultat.

Comme vous pouvez le voir, Predicate dispose de méthodes utiles pour créer des conditions complexes, à l'instar des opérateurs que vous utiliseriez dans une application ordinaire. if alors que Function possède des méthodes qui prennent en charge le chaînage simple.

0 votes

Je n'ai aucune idée de l'importance de tout ça, bien sûr ils ont des méthodes, des noms et des objectifs différents. Pour moi, c'est ça qui tire les ficelles.

3voto

Umar Tahir Points 453

Bien qu'il s'agisse d'un ancien article, je vais résumer les différences entre les deux pour les nouveaux venus.

Prédicat : Pour mettre en œuvre des contrôles conditionnels nous devrions opter pour Predicate .

Fonction : Pour effectuer certaines opérations et renvoyer un résultat nous devrions opter pour la fonction

Prédicat : Le prédicat peut prendre un paramètre de type qui représente le type d'entrée ou le type d'argument.

Fonction : Une fonction peut prendre deux types de paramètres. Le premier représente le type d'argument d'entrée et le second le type de retour.

Prédicat : Predicate définit une fonction abstraite appelée test(). Lorsque vous utilisez le prédicat, vous pouvez dire "tester cette condition" ou "tester cette condition".

Fonction : La fonction définit une fonction abstraite appelée apply(). Lorsque vous utilisez une fonction, vous pouvez dire "appliquer cette fonction" ou "appliquer cette fonction".

Prédicat : Renvoie toujours une valeur booléenne.

Fonction : La fonction peut retourner n'importe quel type de valeur.

Parfois, les gens appellent le prédicat le cas spécail de la fonction. Une autre différence entre eux est qu'ils contiennent différents types de méthodes par défaut et statiques dans leurs interfaces respectives .

2voto

ACV Points 5246

A Predicate ne peut retourner qu'un boolean (résultat de la test() ) tandis que Function effectue une transformation et peut retourner n'importe quoi (résultat de apply() ).

A Predicate est utilisé pour tester une condition.

A Function est utilisé pour effectuer une transformation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X