Ma table de hachage dans Java bénéficierait d'une valeur ayant une structure Tuple. Quelle structure de données puis-je utiliser dans Java pour le faire?
Hashtable<Long, Tuple<Set<Long>,Set<Long>>> table = ...
Je ne pense pas qu'il y ait une classe tuple à usage général dans Java, mais une classe personnalisée pourrait être aussi simple que celle-ci:
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
}
Bien sûr, la manière de concevoir cette classe en termes d’égalité, d’immuabilité, etc., a des implications importantes, en particulier si vous envisagez d’utiliser des instances comme clés de hachage.
javatuples est un projet dédié aux n-uplets en Java.
Unit<A> (1 element)
Pair<A,B> (2 elements)
Triplet<A,B,C> (3 elements)
Apache Commons fournissait des utilitaires communs Java, y compris un Pair . Il implémente Map.Entry
, Comparable
et Serializable
.
Si vous recherchez un tuple Java à deux éléments intégré, essayez AbstractMap.SimpleEntry
.
Dans le prolongement de @maerics Nice answer, j'ai ajouté quelques méthodes utiles:
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "(" + x + "," + y + ")";
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (!(other instanceof Tuple)){
return false;
}
Tuple<X,Y> other_ = (Tuple<X,Y>) 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 existe maintenant une classe pour cela dans Lib standard: javafx.util.Pair.
Et oui, il est standard Java, maintenant que JavaFx est inclus dans le JDK :)
Voici la même question ailleurs, qui inclut un equals
plus robuste, hash
plus robuste que celui auquel les maerics font allusion:
Cette discussion reflète les approches maerics vs ColinD de "devrais-je réutiliser un tuple de classe 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 ce dernier camp; J'ai évolué pour soutenir l'ancien.
Cet objet fournit une implémentation raisonnable d’equals (), renvoyant true si equals () est vrai sur chacun des objets contenus.
Avec lombok , il est facile de déclarer une classe Pair
:
_@Data(staticConstructor = "of")
public class Pair<A, B> {
private final A left;
private final B right;
}
_
Cela générera des getters, un constructeur statique nommé "of", equals()
, hashcode()
et toString()
.
voir @Data
documentation pour plus d'informations
Créez une classe qui décrit le concept que vous modélisez et utilisez-la. Il peut simplement stocker deux Set<Long>
et leur fournir des accesseurs, mais vous devez le nommer pour indiquer en quoi consiste exactement 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<X extends Comparable<? super X>, Y extends Comparable<? super Y>>
extends Tuple<X, Y>
implements Comparable<ComparableTuple<X, Y>>
{
public ComparableTuple(X x, Y y) {
super(x, y);
}
/**
* Implements lexicographic order
*/
public int compareTo(ComparableTuple<X, Y> other) {
int d = this.x.compareTo(other.x);
if (d == 0)
return this.y.compareTo(other.y);
return d;
}
}
Bien que l'article soit assez ancien maintenant et que je comprenne que je ne suis pas très utile, je pense que le travail effectué ici: http://www.pds.ewi.tudelft.nl/pubs/papers/ cpe2005.pdf , aurait été agréable à Java.
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 les tuples sont:
Cette approche augmente
Je vais commencer par un point de vue général sur les n-uplets dans Java et terminer par une implication de votre problème concret.
1) La manière dont les n-uplets sont utilisés dans des langages non génériques est évitée dans Java car ils ne sont pas sécurisés contre les types (par exemple, en Python: Tuple = (4, 7.9, 'python')
). Si vous souhaitez toujours utiliser quelque chose comme un tuple à usage général (ce qui est non recommandé), vous devez utiliser Object[]
ou List<Object>
et convertir les éléments après une vérification avec instanceof
pour assurer la sécurité du type.
Habituellement, les n-uplets 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 un class
pour fournir des valeurs et des méthodes bien définies et adaptées aux types. Cela semble ennuyeux et inutile au début, mais évite les erreurs déjà à compilation.
2) Si vous avez besoin d'un tuple contenant les mêmes (super-) classes Foo
, utilisez Foo[]
, List<Foo>
ou List<? extends Foo>
(ou les équivalents immuables des listes). Comme un tuple n'a pas une longueur définie, cette solution est équivalente.
3) Dans votre cas, vous semblez avoir besoin d'un Pair
(c'est-à-dire un tuple de longueur bien définie 2). Cela rend la réponse de maerics ou l'une des réponses supplémentaires la plus efficace, car vous pourrez réutiliser le code ultérieurement.
Vous pouvez utiliser Google Guava Table