Utilisation de paires ou de 2 tuples en Java

Ma table de hachage en Java bénéficierait d’une valeur ayant une structure de tuple. Quelle structure de données puis-je utiliser en Java pour cela?

Hashtable<Long, Tuple<Set,Set>> table = ... 

Je ne pense pas qu’il existe une classe de tuple à usage général en Java, mais une classe personnalisée pourrait être aussi simple que les suivantes:

 public class Tuple { public final X x; public final Y y; public Tuple(X x, Y y) { this.x = x; this.y = y; } } 

Bien sûr, la conception de cette classe en matière d’égalité, d’immuabilité, etc., a des implications importantes, surtout si vous envisagez d’utiliser des instances comme clés pour le hachage.

javatuples est un projet dédié aux tuples en Java.

 Unit (1 element) Pair (2 elements) Triplet (3 elements) 

Apache Commons a fourni des utilitaires Java communs, y compris une paire . Il implémente Map.Entry , Comparable et Serializable .

Si vous recherchez un tuple Java à deux éléments intégré, essayez AbstractMap.SimpleEntry .

Comme extension de @maerics nice answer, j’ai ajouté quelques méthodes utiles:

 public class Tuple { public final X x; public final Y y; public Tuple(X x, Y y) { this.x = x; this.y = y; } @Override public Ssortingng toSsortingng() { return "(" + x + "," + y + ")"; } @Override public boolean equals(Object other) { if (other == this) { return true; } if (!(other instanceof Tuple)){ return false; } Tuple other_ = (Tuple) other; // this may cause NPE if nulls are valid values for x or y. The logic may be improved to handle nulls properly, if needed. return other_.x.equals(this.x) && other_.y.equals(this.y); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((x == null) ? 0 : x.hashCode()); result = prime * result + ((y == null) ? 0 : y.hashCode()); return result; } } 

Encore 2 cents: à partir de Java 7, il y a maintenant une classe pour cela dans la norme Lib: javafx.util.Pair.

Et oui, c’est Java standard, maintenant que JavaFx est inclus dans le JDK 🙂

Voici exactement la même question ailleurs, qui inclut un équivalent plus robuste, le hash que fait allusion à maerics:

http://groups.google.com/group/comp.lang.java.help/browse_thread/thread/f8b63fc645c1b487/1d94be050cfc249b

Cette discussion continue pour refléter les approches de Maerics vs ColinD de “devrais-je réutiliser une classe Tuple avec un nom non spécifique, ou créer une nouvelle classe avec des noms spécifiques chaque fois que je rencontre cette situation”. Il y a des années j’étais dans le dernier campement; J’ai évolué pour soutenir le premier.

Android Tuple Utils

Cet object fournit une implémentation raisonnable de equals (), renvoyant true si equals () est vrai sur chacun des objects contenus.

Créez une classe décrivant le concept que vous modélisez et utilisez. Il ne peut stocker que deux Set et leur fournir des accesseurs, mais il doit être nommé pour indiquer exactement ce que sont chacun de ces ensembles et pourquoi ils sont regroupés.

Pour compléter la réponse de @ maerics, voici le tuple Comparable :

 import java.util.*; /** * A tuple of two classes that implement Comparable */ public class ComparableTuple, Y extends Comparable> extends Tuple implements Comparable> { public ComparableTuple(X x, Y y) { super(x, y); } /** * Implements lexicographic order */ public int compareTo(ComparableTuple other) { int d = this.x.compareTo(other.x); if (d == 0) return this.y.compareTo(other.y); return d; } } 

Avec lombok, il est facile de déclarer une classe Pair :

 @Data(staticConstructor = "of") public class Pair { private final A left; private final B right; } 

Cela va générer des getters, un constructeur statique nommé “of”, equals() , hashcode() et toSsortingng() .

voir la documentation de @Data pour plus d’informations

Vous pouvez utiliser Google Guava Table

Bien que l’article soit assez ancien maintenant, et même si je comprends que je ne suis pas vraiment très utile, je pense que le travail effectué ici: http://www.pds.ewi.tudelft.nl/pubs/papers/cpe2005.pdf , aurait été sympa en Java grand public.

Vous pouvez faire des choses comme:

 int a; char b; float c; [a,b,c] = [3,'a',2.33]; 

ou

 [int,int,char] x = [1,2,'a']; 

ou

 public [int,boolean] Find(int i) { int idx = FindInArray(A,i); return [idx,idx>=0]; } [idx, found] = Find(7); 

Ici tuples sont:

  • Définis comme des types primitifs – pas de modèles / génériques
  • Stack-répartition si déclaré localement
  • Assigné à l’aide de la correspondance de motif

Cette approche augmente

  • Performance
  • Lisibilité
  • Expressivité

Je vais partir d’un sharepoint vue général sur les tuples en Java et finir avec une implication pour votre problème concret.

1) La manière dont les tuples sont utilisés dans les langages non génériques est évitée en Java car ils ne sont pas sécurisés (par exemple, dans Python: tuple = (4, 7.9, 'python') ). Si vous voulez toujours utiliser quelque chose comme un tuple à usage général (ce qui n’est pas recommandé ), vous devez utiliser Object[] ou List et lancer les éléments après une vérification avec instanceof pour assurer la sécurité du type.

Généralement, les tuples dans un certain paramètre sont toujours utilisés de la même manière avec la même structure. En Java, vous devez définir cette structure explicitement dans une class pour fournir des valeurs et des méthodes bien définies et sécurisées. Cela semble gênant et inutile au début, mais évite les erreurs dès la compilation .

2) Si vous avez besoin d’un tuple contenant les mêmes (super) classes Foo , utilisez Foo[] , List ou List List (ou les contreparties immuables des listes). Un tuple n’ayant pas une longueur définie, cette solution est équivalente.

3) Dans votre cas, vous semblez avoir besoin d’une Pair (c.-à-d. Un tuple de longueur 2 bien définie). Cela rend la réponse de Maerics ou une des réponses supplémentaires la plus efficace possible car vous pouvez réutiliser le code ultérieurement.