Quelle est la différence entre un prédicat et une Interface de fonction dans Java8?

je sais que cela peut être une question très simple sur mais je veux savoir quelle est la différence entre un Predicate et <!-Interface 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 ?

25
demandé sur NullPointer 2018-07-20 18:00:45

6 réponses

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

d'Abord et avant tout un Predicate<T>strictement un boolean-valeur de la fonction:

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

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

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

Le dernier consomme n'importe quel type d'objet comme Predicate<T> active mais peut vary dans le type de retour.

cas D'utilisation de Predicate<T> et Function<T, R>

Le cas d'utilisation de Predicate<T> c'est quand vous 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 vérifier la présence d'un élément d'un flux qui satisfait à une certaine condition en tant que telle de anyMatch,noneMatch,allMatch etc.

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

explication de votre code snippet:

En ce qui concerne l'exemple extrait de code dans votre post Predicate<String> et Function<String, Boolean> sont la même chose en termes de ce qu'ils représentent, c'est à dire qu'ils représentent tous deux une fonction prenant un String renvoi d'un boolean. Cependant, le premier évite de boxe la valeur retournée de booleanBoolean alors que ce dernier ne le fait pas.

cela dit, cela ne signifie pas nécessairement partout où vous pouvez utiliser un Predicate<String> vous pouvez également utiliser un Function<String, Boolean> ou vice versa.

Exemple:

bien que cette compile:

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

Cela ne fonctionne pas:

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

et vice versa:

Tout ceci fonctionne:

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

Cela ne fonctionne pas:

Predicate<String> predicate = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(predicate);
29
répondu Aomine 2018-07-20 20:39:58

dans ce cas il n'y a pas de différence, c'est important seulement pour les choses que vous pouvez appliquer à. Ainsi, par exemple,allMatch attend un Predicate, vous ne pouvez pas passer un Function, même si, logiquement, ils font la même chose.

6
répondu Eugene 2018-07-20 15:04:48

la réponse d'Aominè couvre les différences fondamentales. Je voudrais ajouter que les deux interfaces ont aussi des méthodes par défaut différentes, c'est-à-dire des méthodes que vous pouvez utiliser dans n'importe quelle classe d'implémentation:

  • Predicate<T>
    • Predicate<T> and(Predicate<? super T> other) - renvoie un prédicat composé qui représente un court-circuitage logique et de ce prédicat et d'un autre.
    • Predicate<T> or(Predicate<? super T> other) - retourne un prédicat composé qui représente un court-circuitage logique ou de ce prédicat et de l'autre.
    • negate() - Retourne 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 le after fonction du résultat.
    • <V> Function<V,R> compose(Function<? super V,? extends T> before) - renvoie une fonction composée qui applique d'abord le before fonction à son entrée, puis applique cette fonction du résultat.

Comme vous pouvez le voir, Predicate a des méthodes utiles pour créer des conditions complexes, un peu comme les opérateurs que vous utiliseriez dans un if déclaration, alors que Function a des méthodes qui supportent le chaînage simple.

5
répondu Jens Bannmann 2018-07-21 14:29:18

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

Predicate sert à tester une condition.

Function est utilisé pour faire la transformation.

2
répondu ACV 2018-07-20 16:58:30

il n'y a vraiment pas de différence.

En théorie, il ne devrait pas y avoir de différence fonctionnelle entre Predicate<T> et Function<T, Boolean>. Predicate est juste une fonction qui prend un objet d'un certain type et retourne un booléen. Function est une généralisation qui peut renvoyer n'importe quel type, pas seulement Boolean.

il peut y avoir des détails d'implémentation dans Java lui-même qui les rendent distincts, mais ils devraient être les mêmes en théorie.

un exemple serait si un interface ne pouvait accepter qu'un Predicate<String>, pas Function<String, Boolean.

1
répondu Nathaniel Pisarski 2018-07-20 15:07:46

d'un point de vue technique, un Predicate<T> n'est qu'une fonction de prendre un T et retour d'un résultat primitif booléen. Cependant, du point de vue de l'usage, un Predicate<T> est totalement une notion différente de celle d'un Function<T, Boolean>.

Nous utilisons un Predicate<T> pour effectuer une opération de filtrage, dans un stream par exemple, nous prenons un Stream<T> taille n, filtrer en utilisant un Predicate<T> pour obtenir un flux de données de taille inférieure ou égale à n. Pendant ce temps, un Function<T, Boolean> dans un stream est utilisé pour effectuer une opération de cartographie de transformer un Stream<T> dans un Stream<Boolean>.

Comme vous pouvez le voir, Predicate<T> et Function<T, Boolean> sont techniquement identiques (en ignorant l'emballage Boolean pour plus de simplicité), mais dans un contexte spécifique (stream par exemple), il est totalement une autre histoire que chacun d'eux joue un rôle distinct.

1
répondu marsouf 2018-07-26 15:08:12