web-dev-qa-db-fra.com

Classe de paire générique

En essayant simplement cette question, je l'ai trouvée dans un examen antérieur afin de me préparer à un prochain examen Java.

Fournissez une paire de classe générique pour représenter des paires d'objets. La classe devrait fournir un constructeur, une méthode pour obtenir le premier membre de la paire, une méthode pour obtenir le deuxième membre de la paire, une méthode pour définir le premier membre de la paire, une méthode pour définir le deuxième membre de la paire . La classe doit être paramétrée sur deux types, un pour le premier membre et un pour le second membre de la paire.

Est-ce une implémentation correcte pour cette question?

public class Pair<firstThing, secondThing>{
   private firstThing first;//first member of pair
   private secondThing second;//second member of pair

   public Pair(firstThing first, secondThing second){
     this.first = first;
     this.second = second;
   }

   public void setFirst(firstThing first){
    this.first = first;
   }

   public void setSecond(secondThing second) {
     this.second = second;
   }

   public thing getFirst() {
     return this.first;
   }

   public thing getSecond() {
     return this.second;
   }
}
11
John Curtsy

Presque. J'écrirais ça comme ça:

public class Pair<F, S> {
    private F first; //first member of pair
    private S second; //second member of pair

    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    public void setFirst(F first) {
        this.first = first;
    }

    public void setSecond(S second) {
        this.second = second;
    }

    public F getFirst() {
        return first;
    }

    public S getSecond() {
        return second;
    }
}

Edit: Je suis d'accord avec le commentaire de @ karmakaze. Le code doit ignorer les setters et faire les première et deuxième finales pour le garder immuable. 

17
Claes Mogren

La nécessité d'une classe Pair apparait généralement dans les projets plus importants - je suis sur le point d'en (ré) implémenter une pour le projet actuel (car les implémentations précédentes ne sont pas accessibles).

En général, j'en fais un POJO immuable, avec une fonction de commodité pour créer des instances. Par exemple:

public class Pair<T,U>
{
    public final T first;
    public final U second;
    public static <T,U> Pair<T,U> of(T first, U second);
}

Pour que l'utilisateur final puisse écrire:

return Pair.of (a, b);

et

Pair<A,B> p = someThing ();
doSomething (p.first);
doSomethingElse (p.second);

Comme mentionné ci-dessus, la classe Pair devrait également implémenter hashCode (), equals (), toString () facultatif mais utile, comme éventuellement clone () et compareTo () pour une utilisation lorsque ceux-ci sont pris en charge par T et U - bien que des efforts supplémentaires soient nécessaires est nécessaire pour décrire comment ces contrats sont pris en charge par la classe Pair.

10
simon.watts

Voici une implémentation du SDK Android

/**
 * Container to ease passing around a Tuple of two objects. This object provides a sensible
 * implementation of equals(), returning true if equals() is true on each of the contained
 * objects.
 */
public class Pair<F, S> {
    public final F first;
    public final S second;

    /**
     * Constructor for a Pair.
     *
     * @param first the first object in the Pair
     * @param second the second object in the pair
     */
    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    /**
     * Checks the two objects for equality by delegating to their respective
     * {@link Object#equals(Object)} methods.
     *
     * @param o the {@link Pair} to which this one is to be checked for equality
     * @return true if the underlying objects of the Pair are both considered
     *         equal
     */
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Pair)) {
            return false;
        }
        Pair<?, ?> p = (Pair<?, ?>) o;
        return Objects.equal(p.first, first) && Objects.equal(p.second, second);
    }

    /**
     * Compute a hash code using the hash codes of the underlying objects
     *
     * @return a hashcode of the Pair
     */
    @Override
    public int hashCode() {
        return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
    }

    /**
     * Convenience method for creating an appropriately typed pair.
     * @param a the first object in the Pair
     * @param b the second object in the pair
     * @return a Pair that is templatized with the types of a and b
     */
    public static <A, B> Pair <A, B> create(A a, B b) {
        return new Pair<A, B>(a, b);
    }
}
5
pommedeterresautee
5
gavenkoa

Je pense non. Quote:

"la classe devrait être paramétrée sur deux types ..."

Je pense qu'ils attendent en termes de:

public class Pair<ThingA, ThingB>
3
Suraj Chandran

Après montage, ça a l'air bien.

Cependant, vous devez réellement implémenter les méthodes hashCode et equals, de sorte que deux paires contenant les mêmes objets soient égales, et puissent être utilisées comme clés dans un HashMap. Et toString si vous vous sentez généreux. Ces méthodes ne sont pas nécessaires pour répondre aux exigences qui vous ont été données, mais ce sont les choses qu'un bon programmeur ajouterait.

2
Tom Anderson

Généralement, un type de paire générique a deux paramètres de type générique, pas un - vous pouvez donc avoir (par exemple) un Pair<String, Integer>. C'est généralement plus utile, OMI.

Je suggérerais également que vous pensiez à un nom plus conventionnel pour votre paramètre de type que "chose". Par exemple, vous pouvez utiliser Pair<A, B> ou Pair<T, U>.

2
Jon Skeet

Les Getters sont cassés

public thing getFirst() {
  return thing.first;
}

public thing getSecond() {
  return thing.second;
}

thing devrait être remplacé par this

2
Boris Pavlović

La classe doit être paramétrée sur deux types, un pour le premier membre et un pour le second membre de la paire.

Vous avez un seul paramètre.

vous avez besoin de quelque chose comme Pair<F,S> et utilisez F où vous utilisez thing pour premier et S où thing pour second.

1
Jan Zyka

Apache Commons Lang a une implémentation de paire générique 

https://commons.Apache.org/proper/commons-lang/apidocs/org/Apache/commons/lang3/Tuple/Pair.html

1
raghu

Avez-vous essayé de le coder pour voir si cela fonctionne?

Vous semblez avoir manqué cette partie de l'exigence:

La classe doit être paramétrée sur deux types, un pour le premier membre et un pour le second membre de la paire.

Ce qui signifie que la classe devrait probablement être définie comme quelque chose de plus semblable à:

public class Pair<T1, T2>

et les autres méthodes mises à jour en conséquence. (A propos, j'ai utilisé T1 et T2 pour faire référence aux types car, par convention, un identifiant court - 1 ou 2 caractères est utilisé). 

Également,

return thing.first;

et 

return thing.second;

ne vont pas fonctionner, comme dans votre exemple, thing est un type, pas un objet. Pensez à ce que vous voulez retourner ici. Avez-vous même besoin d'appeler une méthode?

Une fois vos modifications effectuées, codez-les et écrivez un test unitaire ou un simple harnais de tests pour vérifier son fonctionnement.

1
Russell

thing est un Variable de type dans une notation inhabituelle - nous utilisons généralement une dernière lettre majuscule (comme T). Ensuite: une variable de type n'a pas de méthode, donc vos accesseurs ne compileront pas.

Amélioration rapide: remplace tout thing par T

Solution rapide pour les getters:

public T getFirst() {
 return first;
}

public T getSecond() {
 return second;
}

L'une des conditions était de permettre deux types différents pour les membres de la paire. Donc, la signature de classe devrait ressembler à:

public Pair<S,T> {
  private S first;
  private T second;
  //...
}
0
Andreas_D

J'ai implémenté quelque chose de similaire mais avec un générateur statique et des setters chaînés

public class Pair<R, L> {

private R left;
private L right;

public static <K,V> Pair<K, V> of(K k, V v) {
    return new Pair<K,V>(k, v);
}

public Pair() {}

public Pair(R key, L value) {
    this.left(key);
    this.right(value);
}

public R left() {
    return left;
}

public Pair<R, L> left(R key) {
    this.left = key;
    return this;
}

public L right() {
    return right;
}

public Pair<R, L> right(L value) {
    this.right = value;
    return this;
}
}
0
Rodrigo Asensio

Ma version de Pair. Cela gère également compare. PS: La plupart du code provient de AOSP.

package util;

import Java.util.Objects;

public class Pair<F extends Comparable<F>, S extends Comparable<S>>
  implements Comparable<Pair<F, S>> {

    public final F first;
    public final S second;

    /**
     * Constructor for a Pair.
     *
     * @param first  the first object in the Pair
     * @param second the second object in the pair
     */
    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    /**
     * Checks the two objects for equality by delegating to their respective
     * {@link Object#equals(Object)} methods.
     *
     * @param o the {@link Pair} to which this one is to be checked for equality
     * @return true if the underlying objects of the Pair are both considered
     * equal
     */
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Pair)) {
            return false;
        }
        Pair<?, ?> p = (Pair<?, ?>) o;
        return Objects.equals(p.first, first) && Objects.equals(p.second, second);
    }

    /**
     * Compute a hash code using the hash codes of the underlying objects
     *
     * @return a hashcode of the Pair
     */
    @Override
    public int hashCode() {
        return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
    }

    /**
     * Convenience method for creating an appropriately typed pair.
     *
     * @param a the first object in the Pair
     * @param b the second object in the pair
     * @return a Pair that is templatized with the types of a and b
     */
    public static <A extends Comparable<A>, B extends Comparable<B>> Pair<A, B> create(A a, B b) {
        return new Pair<>(a, b);
    }

    @Override
    public int compareTo(Pair<F, S> that) {
        int cmp = this.first.compareTo(that.first);
        if (cmp == 0)
            cmp = this.second.compareTo(that.second);
        return cmp;
    }
}
0
Brajesh Kumar