web-dev-qa-db-fra.com

Quel est le meilleur moyen de renvoyer une paire de valeurs en Java?

C'est un petit problème, car je pourrais facilement créer un cours en binôme pour faire le travail. Cependant, je ne souhaite pas vraiment faire cela, et j’ai le sentiment qu’il devrait exister une méthode simple, intégrée, de type Java, permettant de renvoyer deux valeurs. Quel est le moyen le plus simple et le meilleur de procéder? Des tableaux? Une autre structure de données?

47
Graham

Pour autant que je sache, il n'y a malheureusement pas de représentation intégrée d'une paire en Java (et j'aurais bien aimé qu'il en soit ainsi). Personnellement, lorsque je code un projet dans lequel une classe de paires est souvent utile, je crée une classe générique Pair<T, U> (ce qui est probablement ce à quoi vous pensiez). Le retour d'un tableau est un moyen simple et rapide, mais vous risquez de le regretter plus tard, car les utilisateurs de votre méthode se demanderont si elle peut éventuellement renvoyer plus de deux valeurs.

Quelle que soit la solution que vous choisissez: chaque fois que vous estimez avoir besoin d'une paire, vous devez déterminer si vous avez économisé du temps aujourd'hui en utilisant par exemple une classe Pair générique vaut vraiment la perte d'informations à la prochaine personne qui lit le code (et cette personne pourrait bien être vous dans six mois). L'écriture d'une classe distincte pour le type de retour prend plus de temps, mais elle transmettrait plus d'informations à ceux qui utilisent votre méthode (en particulier, elle indique aux utilisateurs ce que représente la valeur de retour et contient des noms de membres utiles pour les deux valeurs). Si c'est une méthode non publique qui est utilisée seulement à quelques endroits, une paire est plus acceptable.

30
Aasmund Eldhuset

L'utilisation d'une classe de conteneur est le moyen le plus simple.

 public class Pair<T, U> {         
    public final T t;
    public final U u;

    public Pair(T t, U u) {         
        this.t= t;
        this.u= u;
     }
 }
26
Hzyf

La chose la plus proche que j'ai vue d'une "paire" dans les bibliothèques standard est l'interface Map.Entry et les classes AbstractMap.SimpleEntry et AbstractMap.SimpleImmutableEntry qui l'implémentent.

Si les deux objets appartiennent à la même classe, un tableau est plus facile à utiliser.

13
trutheality

Apache Commons Lang3 fournit un résumé Pair class avec quelques implémentations, notamment ImmutablePair et MutablePair.

3
JohnGlynn

Trois approches, toutes pas si géniales:

  1. Lancez votre propre Pair<A, B>. Vous avez dit que vous ne vouliez pas faire ça.
  2. Renvoie un Object[]. Ce n'est pas sûr.
  3. Imiter variables de sortie ou pointeurs en fournissant des tableaux à élément unique en tant que paramètres.

Un exemple de # 3:

public boolean getUserDetails(String userId, String[] lastName, String[] firstName, Date[] dob) {
  assert lastName  != null && lastName.length  == 1;
  assert firstName != null && firstName.length == 1;
  assert dob       != null && dob.length       == 1;
  ...
}

La troisième option rend la vie pénible pour l'appelant.

Donc, comme je l'ai dit, pas de solution de Nice.

En passant, Scala utilise divers cours de tuple (jusqu'à 21 tuple, d'après mes souvenirs) pour vous aider.

2
Dilum Ranatunga

Il existe une classe Pair dans JavaFX, mais vous ne devriez pas l'utiliser. Ce que vous devriez utiliser est quelque chose comme ceci:

// We've skipped imports and package declarations
public final class YourClass {
  /* Assume there is a bunch of stuff here */

  // I don't know what method you're using, so forgive the silly example
  public YourClass.Pair sillyExampleOfPairs(String someString) {
    return new YourClass.Pair(someString, someString.length() * 13);
  }

  @Value // Lombok annotation.
  public static class Pair {
    String text;
    int integer;
  }

  // this is an even more succinct possibility
  @Value public static final class ShorterPair {String text; int integer}
}

Bien que le nom Pair ne soit évidemment pas très bien choisi et que vous deviez choisir un nom plus descriptif, son fonctionnement évident (les champs sont privés et vous avez un getter sur chacun, à cause de l'annotation) ne devrait pas être perdu sur vous. Et bien que oui, il est légèrement plus verbeux que d'utiliser Pair, il est beaucoup plus robuste. Que faire si do devez ajouter un paramètre supplémentaire à la valeur de retour? Vous "seulement" devez alors changer de classe. Et vous pouvez mettre à jour tous les JavaDocs pertinents immédiatement, ce qui est également Nice. Si vous devez changer de type, ils entraîneraient tous les deux une charge de travail similaire.

Tant que vous ajoutez uniquement des éléments, les anciennes méthodes getText () et getInteger () continuent de fonctionner comme avant. Vous évitez également d'avoir à ajouter Yet Another Dependency à vos projets. Ce n'est pas une grande victoire. Avoir Pair disponible, c'est bien pour le prototypage, mais pas pour plus tard.

Mon dernier argument théorique CS-y est que Pair est du même type que Pair. Mais si vous avez Phonebook.Entry (avec String et int) et que vous indiquez Inventory.Item (avec un nom et un certain nombre d'éléments inventoriés à ce jour), ces deux types sont très distincts et ont des effets très distincts. Vous ne pouvez pas mettre l'un dans l'autre. C'est une bonne chose.

Il est également beaucoup plus clair pour nous, pauvres bâtards, de déboguer vos systèmes pour voir quelque chose du type "com.name.project.something.something.Phonebook.Entry" dans une trace de pile que "org.Apache.commons.lang3.Tuple .Paire". L'un d'eux me dit ce que je suis supposé regarder et me donne quelques informations sur pourquoi je vois une paire. L'autre dit ... rien.

Maintenant, vous ne vous inquiétez peut-être pas de devoir taper 3 secondes de plus pour économiser 3 minutes. Mais je choisis de croire en la bonté de ton cœur et en la noblesse de ton âme. Par conséquent, faites la bonne chose.

Écrivez plutôt une petite classe statique.

1
Haakon Løtveit

si les deux sont des entiers, je conseillerais un Java.awt.Point mais sinon, créez simplement une classe conteneur avec deux objets x et y

0

Des experts m'ont dit que face à la question des paires, l'une des deux choses suivantes est vraie:

  1. Vous devez repenser votre structure (cette réponse directe n’aide personne)
  2. Vous devez construire votre propre classe pour tenir la paire

Je dirais que le second cas n’est pas si anormal. Cependant, si ce que vous faites semble trop trivial pour introduire une nouvelle classe, utilisez un Map pourrait travail, comme d’autres l'ont suggéré. Si vous envoyez simplement une seule réponse, alors une Map apparaît un peu trop.

Si une liste de paires semble fonctionner, et que vous devez maintenir l'ordre, vous pouvez essayer un LinkedHashMap afin que cet ordre soit maintenu.

0
Tanner Perrien

Quelques observations de ma part:

  1. Array est intégré, rapide et facile à utiliser, bien qu’il soit impossible d’augmenter sa capacité. Que faire si vous voulez que 3 valeurs soient renvoyées après 3 mois?

  2. ArrayList/autres colletions peuvent être bons, vous permet d'incrémenter la capacité (initialement 10). Notez que Vector peut être excessif par rapport à ArrayList lorsque vous souhaitez uniquement stocker 2 valeurs à récupérer ultérieurement. La carte peut aussi être utile car elle est toujours triée et ordonnée.

  3. Certaines classes définies par l'utilisateur: peut-être une option si est significative (signifie que les données renvoyées sont importantes pour être un bean Java) et que vous souhaitez y stocker plus de 2 entiers. La lisibilité est meilleure si vous ajoutez plus de notes dans sa Javadoc. Peut être étendu à votre guise, ajoutez simplement des champs dans cette classe. Plus lent, mais plus sûr.

0
WesternGun