web-dev-qa-db-fra.com

Utilisation de paires ou de 2 tuples dans Java

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 = ...
284
syker

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.

297
maerics

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)
160
Daniel

Apache Commons fournissait des utilitaires communs Java, y compris un Pair . Il implémente Map.Entry, Comparable et Serializable.

89
rhgb

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

53
at7000ft

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;
    }
}
36
Aram Kocharyan

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 :)

29
Teocali

Voici la même question ailleurs, qui inclut un equals plus robuste, hash plus robuste que celui auquel les maerics font allusion:

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

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.

17
not-just-yeti

Android Tuple Utils

Cet objet fournit une implémentation raisonnable d’equals (), renvoyant true si equals () est vrai sur chacun des objets contenus.

7
see2851

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

7
user180100

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.

6
ColinD

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;
  }
}
5
Alexei Averchenko

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:

  • Défini en tant que types primitifs - pas de modèles/génériques
  • Stack alloué si déclaré localement
  • Assigné en utilisant un filtrage par motif

Cette approche augmente

  • Performance
  • Lisibilité
  • Expressivité
4
Mads Boyd-Madsen

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.

2
Mario Reutter

Vous pouvez utiliser Google Guava Table

2
Ste