web-dev-qa-db-fra.com

Créer un compareTo à une classe générique qui implémente Comparable

J'ai une classe générique avec deux variables de type, qui implémente Java.lang.Comparable.

 La classe publique DoubleKey <K, J> implémente Comparable <DoubleKey <K, J >> {
 
 clé privée K; 
 clé privée J2; 
 
 public DoubleKey (clé K1, clé2) {
 this.key1 = clé1; 
 this.key2 = clé2; 
} 
 
 public K getFirstKey () {
 renvoie this.key1; 
} 
 
 public J getSecondKey () {
 renvoie ceci .key2; 
} 
 
 // besoin d'une interface comparable 
 public int compareTo (DoubleKey <K, J> aThat) {
 .. . 
} 
 
} 

Parce que je l'ai implémenté avec Comparable, je dois écrire la méthode compareTo (). Parce que K, J peut être deTOUT TYPE, je ne parviens pas à les comparer complètement. Y at-il un moyen de pouvoir attraper tous les types possibles (Primitive, Wrapper, Object) dans la comparaison? Merci pour l'aide!

18
Jairo

pour résumer ce qui précède et le transformer en un code fonctionnel, il s’agit de: 

    public class DoubleKey<K extends Comparable<K>, J extends Comparable<J>>
        implements Comparable<DoubleKey<K, J>> {

    private K key1;
    private J key2;

    public DoubleKey(K key1, J key2) {
        this.key1 = key1;
        this.key2 = key2;
    }

    public K getFirstKey() {
        return this.key1;
    }

    public J getSecondKey() {
        return this.key2;
    }

    public int compareTo(DoubleKey<K, J> that) {

        int cmp = this.getFirstKey().compareTo(that.getFirstKey());
        if (cmp == 0)
            cmp = this.getSecondKey().compareTo(that.getSecondKey());
        return cmp;
    }
}
12
olippuner

Souhaitez-vous introduire une exigence selon laquelle K et J ont un ordre naturel que vous pouvez utiliser? Dans ce cas, vous pouvez déclarer votre classe DoubleKey comme ceci:

class DoubleKey<K extends Comparable<K>, J extends Comparable<J>>

Vous pouvez ensuite définir la variable compareTo de votre DoubleKey à votre guise. Vous pouvez faire des choses comme:

getFirstKey().compareTo(aThat.getFirstKey())

Vous ne pouvez toutefois comparer aucune instance de K à une instance de J. Il n'y a pas d'ordre défini sur ces types.

Si ces types n'ont pas nécessairement un ordre naturel (beaucoup n'en ont pas), vous pouvez utiliser un Comparator<K> et un Comparator<J> en tant que paramètres du constructeur de votre DoubleKey. Une classe qui fait déjà cela et que vous pouvez utiliser comme exemple est l'excellent Maps class de Google Guava (voir spécifiquement les méthodes newTreeMap et les limites des types qu'elles acceptent).

8
sjr
 public class DoubleKey <
 K implémente Comparable <K>, 
 J implémente Comparable <J >> 
 implémente Comparable <DoubleKey <K, J >> {
 
 public int compareTo (DoubleKey <K, J> que) {
 int cmp = this.key1.compareTo (that.key1); 
 if (cmp = = 0) cmp = this.key2.compareTo (that.key2); 
 Renvoie cmp; 
} 
} 
4
paulmurray

Première façon: utilisez hashCodes, comme

 public int compareTo(DoubleKey<K,J> aThat){
     getFirstKey().hashCode() + getSecondKey().hashCode() - aThat.getFirstKey().hashCode() +   aThat.getSecondKey().hashCode();
 }

(vous devriez penser plus à la formule)

Deuxième manière: Ajouter un comparateur au constructeur

public DoubleKey(K key1, J key2, Comparator cmp){
0
Stan Kurilin

Comme souvent, il existe une bibliothèque qui peut résoudre votre problème: Apache Commons lang3 . J'utilise souvent Paire <L, R> instances comme clés. Ils mettent en œuvre Comparable.

0
Michael Scheper

Vous devrez définir une règle quand un DoubleKey<K,J> est plus petit, plus grand ou égal à celui-ci. C'est ce que fait la comparaison. Peut-être, c'est ce que je suppose, cela n'a pas beaucoup de sens de comparer aux instances de DoubleKey<K,J>.

Si vous ne prenez pas réellement les soins comment ils sont commandés et que vous devez seulement mettre en œuvre any ordering, essayez ceci:

public int compareTo(DoubleKey<K,J> that){
    // real codes needs checks for null values!
    return (this.key1.toString() + this.key2.toString()).compareTo(that.key1.toString() + that.key2.toString());
}
0
Andreas_D