problème avec le switch [Java] - Java - Programmation
Marsh Posté le 06-06-2002 à 16:01:25
peut pas
Marsh Posté le 06-06-2002 à 16:12:41
fight a écrit a écrit : ok merci decidement ,j'aime pas Java |
stupide comme réaction ...
Marsh Posté le 06-06-2002 à 16:21:02
Tu peux toujours t'amuser à faire un truc du style :
if (ma_chaine.compareTo("AAAAA" ) == 0) {
le_truc_a_faire_qd_c_AAAAA();
return;
}
if (ma_chaine.compareTo("BBBBB" ) == 0) {
le_truc_a_faire_qd_c_BBBBB();
return;
}
// etc...
le_truc_a_faire_qd_c_rien();
Marsh Posté le 06-06-2002 à 16:24:01
fight a écrit a écrit : ok merci decidement ,j'aime pas Java |
tu portes bien ton nom toi
Marsh Posté le 06-06-2002 à 16:25:38
Wons a écrit a écrit : Tu peux toujours t'amuser à faire un truc du style : if (ma_chaine.compareTo("AAAAA" ) == 0) { le_truc_a_faire_qd_c_AAAAA(); return; } if (ma_chaine.compareTo("BBBBB" ) == 0) { le_truc_a_faire_qd_c_BBBBB(); return; } // etc... le_truc_a_faire_qd_c_rien(); |
ou bien :
Code :
|
Marsh Posté le 06-06-2002 à 16:27:12
benou a écrit a écrit : ou bien :
|
oui aussi oui
Décidemment, y'a plein de switch avec les String en Java
Marsh Posté le 12-08-2002 à 21:30:56
y'a pas moyen de résoudre le pb en utilisant la méthode hashcode() ?
Perso, j'ai essayé, mais ça marche pas, alors je sais pas de trop...
Marsh Posté le 12-08-2002 à 21:40:16
squall36 a écrit a écrit : y'a pas moyen de résoudre le pb en utilisant la méthode hashcode() ? Perso, j'ai essayé, mais ça marche pas, alors je sais pas de trop... |
ben d'une par, ce serait pas pratique, et d'autre part, ce sera pas sûr, puisque le hashcode n'identifie pas un Objet de façon unique : tu peux avoir 2 objets dont le haschCode est identique et qui ne sont pas égaux
Marsh Posté le 12-08-2002 à 22:56:47
benou a écrit a écrit : ben d'une par, ce serait pas pratique, et d'autre part, ce sera pas sûr, puisque le hashcode n'identifie pas un Objet de façon unique : tu peux avoir 2 objets dont le haschCode est identique et qui ne sont pas égaux |
ok, bon ben tant pis... vive les "if" alors!
Marsh Posté le 12-08-2002 à 23:03:31
squall36 a écrit a écrit : ok, bon ben tant pis... vive les "if" alors! |
yapamieu !
Marsh Posté le 13-08-2002 à 01:50:33
Juste une remarque en passant. l'instruction switch, du moins celle que je connais en C, C++ et consort (y compris Java) ne s'applique qu'aux entiers. Donc, la remarque "J'aime pas Java", c'est plutôt "Décidément, la prog ça fait chier". Là d'accord.
Marsh Posté le 13-08-2002 à 08:01:41
Cherrytree a écrit a écrit : Juste une remarque en passant. l'instruction switch, du moins celle que je connais en C, C++ et consort (y compris Java) ne s'applique qu'aux entiers. Donc, la remarque "J'aime pas Java", c'est plutôt "Décidément, la prog ça fait chier". Là d'accord. |
Héhé, en Bash, ça marche!
Marsh Posté le 13-08-2002 à 08:37:48
fight a écrit a écrit : ok merci decidement ,j'aime pas Java |
tu connais un langage avec lequel on peut faire des switch sur des chaines de caractères ?
Marsh Posté le 13-08-2002 à 08:52:07
El_Gringo a écrit a écrit : tu connais un langage avec lequel on peut faire des switch sur des chaines de caractères ? |
Le monsieur vient de te dire bash !
Marsh Posté le 13-08-2002 à 09:05:49
Cherrytree a écrit a écrit : Le monsieur vient de te dire bash ! |
Bash... tu parles d'un langage !
Marsh Posté le 13-08-2002 à 09:30:05
El_Gringo a écrit a écrit : Bash... tu parles d'un langage ! |
C'est autant un langage que PHP.
Marsh Posté le 13-08-2002 à 09:31:44
ah, si, c'est un langage! J'ai vu des mecs qu CEA faire des programmes super de la mort en Bash....Bon, d'accord, ils étaient obligés de les modifier à chaque changement de version de tar, find ou grep, parce que ces gros nazes ne connaissaient pas les codes de retour sous Unix, mais sinon, ça marchait... D
CEA : Blerow power!!
Marsh Posté le 13-08-2002 à 09:35:14
gfive a écrit a écrit : CEA : Blerow power!! |
Pas tous ! Ma copine y a officié pendant un stage !
Marsh Posté le 13-08-2002 à 09:36:30
bah, j'ai pas parlé des stagiaires, hé!! J'y ai passé 10 mois comme scientifique du contingent....Quand je leur ai parlé de Java pour un projet, ils m'ont dit : "Tu comprends, Java, chez nous, personne connaît, alors si tu l'utilise, on sera obligé de l'apprendre pour maintenir le projet, donc, non."
Pouf pouf..
Marsh Posté le 13-08-2002 à 09:41:16
gfive a écrit a écrit : bah, j'ai pas parlé des stagiaires, hé!! J'y ai passé 10 mois comme scientifique du contingent....Quand je leur ai parlé de Java pour un projet, ils m'ont dit : "Tu comprends, Java, chez nous, personne connaît, alors si tu l'utilise, on sera obligé de l'apprendre pour maintenir le projet, donc, non." Pouf pouf.. |
Arf !
Marsh Posté le 13-08-2002 à 21:08:10
c'est pas possible de faire des swichs sur des strings en VB ?
Marsh Posté le 13-08-2002 à 21:51:10
Pour en revenir aux hash :
Si tu fais un switch, c'est que tu as un nombre faible de cas, donc il y a peu de chances que ça foire.
Sinon, autre idée :
Une ptite HashMap
map.put(la_string, une_methode)
avec methode étant la méthode qui fait le boulot. java.reflect.method ou quelque chose comme ça.
il suffit d'initialiser la hashmap, et ensuite le switch s'écrit
(Method)(map.get(la_string)).invoke(quelquechose, parametres)
Pour quelquechose : je mettrais bien self
pour les paramètres : un tableau vide
a+
Marsh Posté le 14-08-2002 à 01:49:54
_gtm_ a écrit a écrit : Si tu fais un switch, c'est que tu as un nombre faible de cas, donc il y a peu de chances que ça foire. Sinon, autre idée : Une ptite HashMap map.put(la_string, une_methode) avec methode étant la méthode qui fait le boulot. java.reflect.method ou quelque chose comme ça. il suffit d'initialiser la hashmap, et ensuite le switch s'écrit (Method)(map.get(la_string)).invoke(quelquechose, parametres) Pour quelquechose : je mettrais bien self pour les paramètres : un tableau vide a+ |
tin mais vous êtes tordu, c'est pas vrai !
d'ailleurs, à mon avis, c'est un post bidon, donc je répond pas
Marsh Posté le 14-08-2002 à 10:30:39
Marsh Posté le 14-08-2002 à 11:18:05
rien justement. Par contre le switch je trouve ca pourris perso
Marsh Posté le 14-08-2002 à 11:27:46
benou a écrit a écrit : tin mais vous êtes tordu, c'est pas vrai ! d'ailleurs, à mon avis, c'est un post bidon, donc je répond pas |
Euh.. j'étais sérieux quand je disais ça!
Une fois l'initialisation faite, je te mets au défi de trouver quelque chose de plus rapide en java...
Marsh Posté le 14-08-2002 à 11:31:07
DarkLord a écrit a écrit : rien justement. Par contre le switch je trouve ca pourris perso |
Ouais, c'est vrai!
Z'avez qu'a faire un bon design de classes et utiliser l'héritage.
Marsh Posté le 14-08-2002 à 13:56:43
_gtm_ a écrit a écrit : Euh.. j'étais sérieux quand je disais ça! Une fois l'initialisation faite, je te mets au défi de trouver quelque chose de plus rapide en java... |
1 - c'est vachement plus long à écrire
2 - c'est illisible
3 - c'est restrictif : un seul appel de méthode par cas
4 - c'est lent : l'invocation dynamique c'est pas ce qu'il y a de plus rapide
5 - c'est gourmand en mémoire : une Map à stocker pour rien
6 - ca engendre un nombre de calculs bien plus important qu'un simple equals
7 - quand tu fais un get sur une HasMap, ca calcul au moins 1 equals sur la clef => de toute façon le equals sera calculé.
8 - c'est vraiment tordu
9 - quand on connait pas ... on affirme pas
Marsh Posté le 14-08-2002 à 13:57:42
_gtm_ a écrit a écrit : Z'avez qu'a faire un bon design de classes et utiliser l'héritage. |
c'est toi qui parle de bon design après ce que tu viens de dire ?
et puis une série de equals sur des chaînes de caractères, c'est très fréquent et souvent obligatoire ! ca n'a rien à vior avec le design d'une appli !
Marsh Posté le 14-08-2002 à 14:06:58
benou a écrit a écrit : c'est toi qui parle de bon design après ce que tu viens de dire ? et puis une série de equals sur des chaînes de caractères, c'est très fréquent et souvent obligatoire ! ca n'a rien à vior avec le design d'une appli ! |
et encore moins avec l'héritage
Marsh Posté le 14-08-2002 à 14:19:23
1 - c'est vachement plus long à écrire
> faut pas être fainéant quand même. Et en plus il y a pas mal de trucs réutilisables, donc c'est pas perdu
2 - c'est illisible
> Ca dépend de comment on l'écrit
3 - c'est restrictif : un seul appel de méthode par cas
> C'est propre : une chaîne, une méthode. Rien n'empêche d'appeler d'autres méthodes dans une méthode de traitement.
4 - c'est lent : l'invocation dynamique c'est pas ce qu'il y a de plus rapide
5 - c'est gourmand en mémoire : une Map à stocker pour rien
> On n'a rien sans rien.
6 - ca engendre un nombre de calculs bien plus important qu'un simple equals
> voir en bas
7 - quand tu fais un get sur une HasMap, ca calcul au moins 1 equals sur la clef => de toute façon le equals sera calculé.
> il me semble que la HashMap ne compare pas les clés mais les valeurs de hachage.
Une valeur de hachage est calculée pour chaque clé de la map. C'est pendant l'initialisation, donc c'est pas important. Ensuite une valeur de hachage est calculée à chaque fois qu'on veut trouver l'action correspondant à une chaîne. Le calcul d'une valeur de hachage est équivalennt à la comparaison de chaines au niveau du temps d'execution.
Ensuite on utilise les tables de hachage pour faire une première recherche dans l'ensemble des valeurs. Ici on ne compare que des valeurs de hachage, ce qui est beaucoup plus rapide que de comparer des chaines.
Il y aura ensuite peut-être des comparaisons de chaînes à faire (chaînes qui ont le même valeur de hachage), mais sur un ensemble beaucoup plus réduit que la liste initiale.
Conclusion:la recherche dans une table de hachage de n éléments prend beaucoup moins de temps que la comparaison de n/2 chaines (n/2 pour avoir le cas moyen). C'est d'ailleurs pour ça que les tables de hachages ont été inventées.
8 - c'est vraiment tordu
> c'est l'idée de vouloir faire un switch qui est tordue depuis le début. Et puis je serais curieux de voir le code des parseurs SAX. Ca marche certainement pas à coup de switch et de ifs
9 - quand on connait pas ... on affirme pas
> J'ai pas affirmé, je t'ai mis au défi de trouver mieux. Je n'ai pas vu de proposition
Marsh Posté le 14-08-2002 à 14:29:32
--greg-- a écrit a écrit : et encore moins avec l'héritage |
Une ptit exemple...
Prenons un doc texte qui ontient une série de commandes
Version avec switch (je me permets les switch sur les chaines, on peut tranformer en if si vous voulez chipoter)
switch(commande)
{
case ("a" ) :
{
executer
}
case ("b" ) :
{
executer autre chose
}
}
une version sans switch
public abstract class CommandHandler
{
public abstract void Handle();
}
public class aHandler()
{
public void Handle()
{
faire quelque chose
}
}
public class bHandler()
{
public void Handle()
{
faire autre chose
}
}
public class root
{
HashMap map = new map();
public void init()
{
map.put("a", new aHandler());
map.put("b", new bHandler());
}
public void MakeAction(String action)
{
((CommandHandler)(map.get(action))).Handle();
}
}
Donc voilà comment j'ai remplacé une série de switches par une résolution dynamique de méthode.
On y trouve de tout : un peu d'héritage et un peu de design. Mais plus de switchs !
Marsh Posté le 14-08-2002 à 14:47:19
ouais
vu comme ça. pq pas.
mais c un peu lourd pour etre appliqué à toutes les applications ou on pourrait utiliser des if/else...
Marsh Posté le 14-08-2002 à 14:53:12
_gtm_, dans certain cas, c utile ton truc, mais dans d'autres (comme ds ton exemple), ça alourdit plus qu'autre chose...
Marsh Posté le 14-08-2002 à 14:57:03
_gtm_ a écrit a écrit : Une ptit exemple... Prenons un doc texte qui ontient une série de commandes Version avec switch (je me permets les switch sur les chaines, on peut tranformer en if si vous voulez chipoter) switch(commande) { case ("a" ) : { executer } case ("b" ) : { executer autre chose } } une version sans switch public abstract class CommandHandler { public abstract void Handle(); } public class aHandler() { public void Handle() { faire quelque chose } } public class bHandler() { public void Handle() { faire autre chose } } public class root { HashMap map = new map(); public void init() { map.put("a", new aHandler()); map.put("b", new bHandler()); } public void MakeAction(String action) { ((CommandHandler)(map.get(action))).Handle(); } } Donc voilà comment j'ai remplacé une série de switches par une résolution dynamique de méthode. On y trouve de tout : un peu d'héritage et un peu de design. Mais plus de switchs ! |
Ouais en effet -> double dispatching. Seul inconvénient c'est que tu dois introduire de nouvelle classes dans ce cas ci, c'est pas toujours très intéressant... (surtout pour des petits trucs de ce style).
En génèral tu fais le double dispatching quand t'as des "if unObjet instanceOf UneClasse then unObjet.blabla() else if unAutreObjet instanceOf UneAutreClasse then unAutreObjet.bloblo() else if blablabla..."
dans ce cas le code est moins évolutif et sale (si j'écrivais ca dans un de mes projets, je me fais tuer).
Et puis pour ta méthode avec des fonctions de hashage, je crois que si tu remplaces cette fonction par une fonction injective (donc one-to-one) pour garantir une valeur unique pour chaque string, tu élimines l'inconvénient de la fonction de hashage (et l'utilisation d'un hashmap). Par exemple, un string "blabla":
pour le premier 'b' -> valeur ASCII (ou qqchose d'autre) de 'b'et ainsi de suite. Puis tu construit ta valeur unique -> valAscii('b' (par exemple 212) valAscii('a' (par exemple 211) valAscii('l' (par exemple 253) ... tu les colles l'un à l'autre et tu obtiens une valeur unique sur lequel tu sais switché -> 212211253212211253... peut-être qu'un "if then else" est plus appoprié...
[edit]j'avais oublié de mettre les méthodes [/edit]
Marsh Posté le 14-08-2002 à 14:57:34
Bon, voila quelques classes qui illustrent l'idée précédente (pas celle avec l'héritage, mais celle avec methode.invoke)
---------------------------------------------------------------
D'abord une classe générale qui sert partout :
import java.util.HashMap;
import java.lang.reflect.*;
public class CommandDispatcher
{
private HashMap map;
private Class handlerClass;
private Class[] nullParamC = {};
private Object[] nullParamO = {};
public CommandDispatcher(Class handlerClass)
{
map = new HashMap();
this.handlerClass = handlerClass;
}
public void addCommand(String commandName)
throws NoSuchMethodException
{
Method m = handlerClass.getMethod("handle"+commandName, nullParamC);
map.put(commandName, m);
}
public void handleCommand(String commandName, Object target)
throws NoSuchMethodException
{
try
{
((Method) map.get(commandName)).invoke(target, nullParamO);
}
catch (Exception e)
{
throw new NoSuchMethodException("The action "+commandName+" does not exist." );
}
}
}
---------------------------------------------------------------
Et maintenant la classe qui fait le switch :
Vous remarquerez qu'on ne rajoute qu'une ligne par nouvelle commande (en plus de la fonction qui traite la commande bien sûr)
import prometag4.util.CommandDispatcher;
public class commandDispatcherTest
{
private CommandDispatcher dispatcher;
public commandDispatcherTest()
{
dispatcher = new CommandDispatcher(this.getClass());
try
{
dispatcher.addCommand("A" );
dispatcher.addCommand("B" );
}
catch (NoSuchMethodException ex)
{
}
}
public void HandleA()
{
// something
}
public void HandleB()
{
// something else
}
public void HandleAction(String commandName)
{
try
{
dispatcher.handleCommand(commandName, this);
}
catch (NoSuchMethodException ex)
{
}
}
}
Remarque : ça compile mais j'ai pas testé si ça fait vraiment ce que ça doit faire.
Marsh Posté le 14-08-2002 à 15:08:08
MelloW a écrit a écrit : Ouais en effet -> double dispatching. Seul inconvénient c'est que tu dois introduire de nouvelle classes dans ce cas ci, c'est pas toujours très intéressant... (surtout pour des petits trucs de ce style). En génèral tu fais le double dispatching quand t'as des "if unObjet instanceOf UneClasse else if unAutreObjet instanceOf UneAutreClasse else if blablabla..." dans ce cas le code est moins évolutif et sale (si j'écrivais ca dans un de mes projets, je me fais tuer). Et puis pour ta méthode avec des fonctions de hashage, je crois que si tu remplaces cette fonction par une fonction injective (donc one-to-one) pour garantir une valeur unique pour chaque string, tu élimines l'inconvénient de la fonction de hashage (et l'utilisation d'un hashmap). Par exemple, un string "blabla": pour le premier 'b' -> valeur ASCII (ou qqchose d'autre) de 'b'et ainsi de suite. Puis tu construit ta valeur unique -> valAscii('b' (par exemple 212) valAscii('a' (par exemple 211) valAscii('l' (par exemple 253) ... tu les colles l'un à l'autre et tu obtiens une valeur unique sur lequel tu sais switché -> 212211253212211253... peut-être qu'un "if then else" est plus appoprié... |
Pour les nouvelles classes : voir le nouvel exemple de code
Sinon, c'est pas du double dispatching. Le double dispatching, c'est quand le choix de la fonction dépend de 2 paramètres (exemple typique : on veut chercher la fonction qui calcule l'intersection entre deux objets - cette fonction dépend du type des deux objets). Ici, la fonction ne dépend que du nom de fonction, donc c'est un simple dispatching.
Et ensuite pour l'histoire de la fonction injective : rien n'empêche de redéfinir la fonction de hachage.
Par contre, ta proposition de valeur unique, soit c'est n'importe quoi, soit j'ai pas compris ce que tu proposes : On veut une valeur unique, mais dans un interval compatible avec switch. Donc mettre bout à bout des valeurs ascii, ça sert à rien du tout (et en plus ça fait vraiment rien, puisque la chaine c'est deja une suite de valeurs ascii).
Marsh Posté le 14-08-2002 à 15:32:41
_gtm_ a écrit a écrit : Pour les nouvelles classes : voir le nouvel exemple de code Sinon, c'est pas du double dispatching. Le double dispatching, c'est quand le choix de la fonction dépend de 2 paramètres (exemple typique : on veut chercher la fonction qui calcule l'intersection entre deux objets - cette fonction dépend du type des deux objets). Ici, la fonction ne dépend que du nom de fonction, donc c'est un simple dispatching. Et ensuite pour l'histoire de la fonction injective : rien n'empêche de redéfinir la fonction de hachage. Par contre, ta proposition de valeur unique, soit c'est n'importe quoi, soit j'ai pas compris ce que tu proposes : On veut une valeur unique, mais dans un interval compatible avec switch. Donc mettre bout à bout des valeurs ascii, ça sert à rien du tout (et en plus ça fait vraiment rien, puisque la chaine c'est deja une suite de valeurs ascii). |
C'est qu'on a pas la même définition de double dispatching -> http://www.chimu.com/publications/ [...] ching.html
Et pour la valeur unique je crois que t'as pas compris (mon explication était pas brillante...):
'b' 'l' 'a' 'b' 'l' 'a'
^ ^ ^ ^ ^ ^
| | | | | |
205 223 204 205 223 204
total (une addition avec des multiplication) = 205223204205223204 -> une valeur unique, mais par contre je sais si ca trouve dans l'intervalle du switch... je proposais cela pcq le switch accepte pas les strings apparement (en java) et que de cette facon tu obtiens un chiffre unique pour chaque string
Marsh Posté le 06-06-2002 à 16:00:12
Voila, en fait, le principe c faire un switch en java sur une variable qui est de type String, toutes les bonnes idées sont les bienvenues