Concept : cette interface ne requiert aucun argument en entrée, mais produit une valeur de type T. Elle agit comme un fournisseur d'objets à la demande.
import java.time.LocalDate;
import java.util.function.Supplier;
import java.util.UUID;
// Exemple 1 : fournir une chaîne de caractères
Supplier<String> idGenerateur = () -> UUID.randomUUID().toString();
System.out.println(idGenerateur.get()); // Génère un identifiant unique
// Exemple 2 : fournir la date du jour
Supplier<LocalDate> dateActuelle = () -> LocalDate.now();
System.out.println(dateActuelle.get()); // Affiche la date courante
// Exemple 3 : création différée d'objets coûteux
Supplier<ConnexionBaseDeDonnees> connexionSupplier = () ->
new ConnexionBaseDeDonnees("jdbc:mysql://localhost:3306/mabase");
// L'objet n'est instancié que lors de l'appel à get()
// ConnexionBaseDeDonnees connexion = connexionSupplier.get();
Cnosumer<T>
Concept : cette interface accepte un paramètre de type T en entrée, mais ne retourne rien. Elle consomme ou traite les données passées.
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
// Exemple 1 : traitement simple
Consumer<String> afficheur = s -> System.out.println("Message : " + s);
afficheur.accept("Bonjour"); // Sortie : Message : Bonjour
// Exemple 2 : modification d'un objet
Consumer<Compte> activateur = compte -> {
compte.setStatut("ACTIF");
compte.setDerniereMiseAJour(LocalDate.now());
};
// Exemple 3 : itération sur une collection
List<Integer> nombres = Arrays.asList(10, 20, 30);
Consumer<Integer> calculateur = n -> {
int carre = n * n;
System.out.println("Carré de " + n + " : " + carre);
};
nombres.forEach(calculateur);
// Sortie :
// Carré de 10 : 100
// Carré de 20 : 400
// Carré de 30 : 900
Function<T,R>
Concept : cette interface prend un arguement de type T et renvoie un résultat de type R. Elle sert à transformer des données d'un type vers un autre.
import java.util.List;
import java.util.stream.Collectors;
import java.util.function.Function;
// Exemple 1 : conversion de type
Function<String, Integer> longueurChaine = s -> s.length();
int longueur = longueurChaine.apply("Interface"); // Retourne 9
// Exemple 2 : transformation d'objet
Function<Utilisateur, ProfilUtilisateur> versProfil = utilisateur -> {
ProfilUtilisateur profil = new ProfilUtilisateur();
profil.setNomComplet(utilisateur.getPrenom() + " " + utilisateur.getNom());
profil.setEmail(utilisateur.getAdresseEmail());
return profil;
};
// Exemple 3 : utilisation dans un Stream
List<String> produits = Arrays.asList("Ordinateur", "Téléphone", "Tablette");
List<Integer> longueurs = produits.stream()
.map(longueurChaine)
.collect(Collectors.toList()); // Résultat : [10, 9, 7]
Predicate<T>
Concept : cette interface évalue une condition sur un argument de type T et retourne un booléen. Elle est utilisée pour la validation ou le filtrage.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.function.Predicate;
// Exemple 1 : vérification numérique
Predicate<Integer> estPositif = n -> n > 0;
boolean test = estPositif.test(5); // Retourne true
// Exemple 2 : validation de chaîne
Predicate<String> contientEspace = s -> s != null && s.contains(" ");
System.out.println(contientEspace.test("Hello World")); // true
// Exemple 3 : composition de prédicats
Predicate<Employe> salaireEleve = e -> e.getSalaire() > 50000;
Predicate<Employe> experienceLongue = e -> e.getAnneesExperience() >= 5;
Predicate<Employe> candidatIdeal = salaireEleve.and(experienceLongue);
// Exemple 4 : filtrage dans un Stream
List<Double> mesures = Arrays.asList(12.5, -3.7, 0.0, 45.2);
List<Double> valeursValides = mesures.stream()
.filter(v -> v > 0) // Utilisation directe d'un prédicat
.collect(Collectors.toList()); // Résultat : [12.5, 45.2]
Utilisation combinée
// Traitement de données d'employés
List<Employe> equipe = Arrays.asList(
new Employe("Alice", 28, 55000),
new Employe("Bob", 35, 75000),
new Employe("Charlie", 42, 48000)
);
// Définition des interfaces fonctionnelles
Predicate<Employe> senior = e -> e.getAge() > 30;
Function<Employe, String> extraireNom = Employe::getNom;
Consumer<String> journal = nom -> System.out.println("Employé senior : " + nom);
// Application en pipeline
equipe.stream()
.filter(senior)
.map(extraireNom)
.forEach(journal);
// Sortie :
// Employé senior : Bob
// Employé senior : Charlie
// Application à un système de cache
public class GestionnaireCache {
private CacheDistribue cache;
public Object obtenirAvecFallback(String cle, Supplier<Object> sourceDonnees) {
Object valeurCache = cache.recuperer(cle);
if (valeurCache == null) {
valeurCache = sourceDonnees.get(); // Appel différé
cache.stocker(cle, valeurCache);
}
return valeurCache;
}
}
Comparaison des interfaces
| Interface | Paramètre | Retour | Utilsiation typique |
|---|---|---|---|
| Supplier<T> | Aucun | T | Fourniture de données, instanciation différée |
| Consumer<T> | T | Aucun | Traitement, effets de bord, journalisation |
| Function<T,R> | T | R | Conversion, mappage, calculs |
| Predicate<T> | T | boolean | Filtrage, validation, conditions |