2012-05-06 1 views
2

J'essaie donc, à toutes fins utiles, de réaliser pour moi-même une version java de l'algorithme STL de C++ pour les paramètres vectoriels. Jusqu'à présent, mon code (ce qui est probablement fondamentalement erroné) ressemble à ceci:Prédéfinir la multiplication pour les génériques en Java

public static<T,K> double inner_product(Vector<T> v1, Vector<K> v2) 
{ 
    double isum = 0; 
    for(int i=0;i<v1.size()&&i<v2.size();i++) 
    { 
     isum+=v1.elementAt(i)*v2.elementAt(i); 
    } 

    return isum; 
} 

Le problème est que le * opérateur n'est pas défini pour les types T, K. Cependant ma connaissance à ce jour ne couvre pas les opérateurs prédéfinir , mais pour autant que je sache, ce n'est pas possible en Java aussi. Toute aide serait appréciée dans la façon de réaliser la fonction de prendre des génériques. Merci d'avance.

Répondre

3

Il n'y a pas belle façon de faire, pour deux raisons:

  1. paramètres de type (T, K) doit faire référence aux types d'objets, pas aux primitives.
  2. Java n'a pas de surcharge d'opérateur.

Le plus proche que vous pouvez obtenir est quelque chose comme ça (modulo les erreurs de syntaxe, mes génériques sont rouillés):

public static<T extends Number,K extends Number> double inner_product(Vector<T> v1, Vector<K> v2) 
{ 
    double isum = 0; 
    for(int i=0;i<v1.size()&&i<v2.size();i++) 
    { 
     isum+=v1.elementAt(i).doubleValue()*v2.elementAt(i).doubleValue(); 
    } 

    return isum; 
} 

Cela fonctionne pour les emballages des objets autour de types primitifs, c.-à-Double mais pas double,

De même, comme votre version, cela renvoie double, peu importe le type qui a été transmis. Et à cause de l'effacement de type, c'est assez difficile à résoudre.

+0

Cette implémentation a fait l'affaire. Je vous remercie. – nutter

2

T doit avoir une méthode définie comme mutliply de sorte que vous pouvez l'appeler avec un V

interface T { 
    double multiply(V v); 
} 

public static<T,K> double inner_product(Vector<T> v1, Vector<K> v2) { 
    double isum = 0; 
    for(int i=0; i<v1.size() && i<v2.size(); i++) { 
     isum += v1.elementAt(i).multiply(v2.elementAt(i)); 
    } 
    return isum; 
} 

à mon humble avis Vector remplacée par la liste dans les bibliothèques Collections Java 1.2 en 1998. En utilisant la liste peut être un meilleur choix.

Avez-vous vraiment besoin qu'il soit générique? Je voudrais simplement utiliser deux

public static double inner_product(List<Double> v1, List<Double> v2) { 
    double isum = 0; 
    for(int i=0; i<v1.size() && i<v2.size(); i++) 
     isum += v1.get(i) * v2.get(i); 

    return isum; 
} 

ou pour l'utilisation efficace à double [] ou

TDoubleArrayList
public static double inner_product(double[] v1, double[] v2) { 
    double isum = 0; 
    for(int i=0; i<v1.size() && i<v2.size(); i++) 
     isum += v1[i] * v2[i]; 

    return isum; 
} 
+0

'Vector' n'a pas été remplacé; c'est toujours parfaitement valide si vous avez besoin d'un tableau de redimensionnement synchronisé.Pour l'autre 99% des cas, utilisez 'ArrayList', qui implémente' List', donc vous pouvez en effet accepter les arguments 'List' ici. – Thomas

+0

Je suppose qu'il n'a pas besoin du tableau pour être synchronisé, mais j'utiliserais 'Collections.synchronizedList (new ArrayList())' de préférence si vous l'avez fait. À mon humble avis, Bien que valable pour utiliser Vector, c'est plutôt rare que c'est le meilleur choix. –

+0

Malheureusement, j'ai besoin d'être générique, car sinon j'écris deux fonctions différentes avec des opérateurs différents pour la même chose. – nutter

1

Il n'y a pas de surcharge d'opérateur en Java et l'opérateur de multiplication s'applique uniquement aux types primitifs numériques. Si vous devez le faire sur les types génériques, vous devrez les faire mettre en œuvre une interface qui permet de les transformer en double:

public interface DoubleProvider 
    double getDouble(); 
} 

Et puis, vous pouvez définir la méthode suivante:

public static <T extends DoubleProvider, K extends DoubleProvider> double innerProduct(Iterable<T> v1, Iterable<K> v2) { 
    Iterator<T> it1 = v1.iterator(); 
    Iterator<K> it2 = v2.iterator(); 
    double sum = 0D; 
    while (it1.hasNext() && it2.hasNext()) { 
     T t = it1.next(); 
     K k = it2.next(); 
     sum += t.getDouble() * k.getDouble(); 
    } 
    return sum; 
} 

Remarquez comment mon code

  • respecte les conventions de nommage Java
  • acepts tout type de Iterable, plutôt que l'obsolète Ve ctor (qui ne devrait plus être utilisé depuis Java 1.2)