Introduction aux conteneurs de données multiples
La bibliothèque open-source Hutool pour Java propose un vaste éventail d'utilitaires conçus pour éliminer le code répétitif. Parmi ses composants, les classes Pair, Triple et Tuple offrent des mécanismes robustes pour regrouper des données hétérogènes. Elles sont particulièrement appréciées pour retourner plusieurs valeurs depuis une méthode sans avoir à définir des classes DTO (Data Transfer Object) temporaires.
- Intégration de la dépendance Maven
<dependency>
<groupId>org.dromara.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>6.0.0-M12</version>
</dependency>
- Concepts fondamentaux : Pair, Triple et Tuple
2.1. La classe Pair
La structure Pair est conçue pour stocker exactement deux éléments, généralement identifiés comme une clé (left) et une valeur (right). Elle est idéale pour les associations binaires.
- Architecture binaire : Stocke deux génériques distincts.
- Immuable : Les instances ne peuvent pas être altérées après leur initialisation, assurant la sécurité dans les contextes multithreadés.
- Cas d'usage : Coordonnées géographiques, associations clé-valeur simples, retour de résultats binaires.
2.2. La classe Triple
Héritant de Pair, la classe Triple étend cette logique en ajoutant un troisième élément (middle). Elle conserve les mêmes garanties d'immuabilité.
- Architecture ternaire : Permet de lier trois concepts distincts.
- Cas d'usage : Configuration à trois paramètres, descriptions d'entités complexes (ex: nom, taille, poids).
2.3. La classe Tuple
Contrairement aux structures à taille fixe, Tuple permet de stocker un nombre arbitraire d'éléments. Bien que très flexible, elle reste strictement immuable.
- Flexibilité dimensionnelle : Accepte N éléments, définis à la création.
- Accès par index : Les éléments sont récupérés via leur position (0, 1, 2, etc.).
- Cas d'usage : Agrégation de métriques, export de lignes de données, passage de multiples paramètres.
- Manipulation et cas d'usage de Pair
3.1. Instanciation et mise à jour simulée
Puisque les objets sont immuables, la "modification" consiste en réalité à instancier un nouvel objet avec les valeurs mises à jour.
Pair<String, Double> articlePrix = Pair.of("Clavier Mécanique", 89.99);
// Simulation de mise à jour via une nouvelle instance
Pair<String, Double> prixPromo = Pair.of(articlePrix.getLeft(), 75.50);
String reference = prixPromo.getLeft();
double montantFinal = prixPromo.getRight();
3.2. Scénarios d'application
La classe Pair excelle dans les situations nécessitant une association forte et typée entre deux valeurs :
- Coordonnées et géolocalisation :
Pair<Double, Double> gps = Pair.of(48.8566, 2.3522); - Retour de validation :
Pair<Boolean, String> resultat = Pair.of(true, "Formulaire valide"); - Tri de flux de données : Utilisation comme clé de tri temporaire.
List<Pair<String, Integer>> employesScores = employes.stream()
.map(emp -> Pair.of(emp.getNom(), calculerPerformance(emp)))
.sorted(Comparator.comparingInt(Pair::getRight).reversed())
.collect(Collectors.toList());
- Exploitation de la structure Triple
L'extraction des données d'un Triple s'effectue via les méthodes getLeft(), getMiddle() et getRight().
Triple<String, Integer, Double> meteoVille = Triple.of("Lyon", 65, 18.5);
String ville = meteoVille.getLeft();
int humidite = meteoVille.getMiddle();
double temperature = meteoVille.getRight();
Applications typiques :
- Dimensions d'affichage :
Triple<Integer, Integer, Double> ecran = Triple.of(1920, 1080, 24.5); - Règles métier à seuils :
Triple<BigDecimal, BigDecimal, Double> remise = Triple.of(min, max, taux); - Configuration réseau :
Triple<String, String, Integer> dbConfig = Triple.of("jdbc:mysql", "localhost", 3306);
- Puissance et flexibilité de Tuple
Le Tuple est idéal lorsque le nombre de valeurs à regrouper dépasse trois ou n'est pas strictement défini à l'avance.
Tuple configServeur = Tuple.of("192.168.1.10", 8443, true, "TLSv1.3");
String ip = configServeur.get(0);
int port = configServeur.get(1);
boolean sslActive = configServeur.get(2);
String protocole = configServeur.get(3);
Domaines de prédilection :
- Statistiques agrégées :
Tuple stats = Tuple.of(1500, 85.4, 12.3, 0.05);(count, mean, stddev, p-value) - Lignes d'export CSV :
Tuple ligne = Tuple.of("ID_01", "Produit A", "2023-10-25", "En stock"); - Événements asynchrones : Regroupement de multiples attributs d'un message avant sérialisation.
Le principal avantage du Tuple réside dans sa capacité à transporter des données hétérogènes sans surcharge syntaxique. Toutefois, l'absence de noms de champs explicites (contrairement à un objet métier) nécessite une documentation rigoureuse ou une convention de nommage claire pour maintenir la lisibilité du code.