Utiliser un tableau comme une instruction de casse dans switch

J’essaie de faire quelque chose comme ça, c’est-à-dire utiliser un tableau dans une instruction switch. Est-ce possible en Java? Si ce n’est pas le cas, veuillez expliquer une solution possible.

boolean[] values = new boolean[4]; values[0] = true; values[1] = false; values[2] = false; values[3] = true; switch (values) { case [true, false, true, false]: break; case [false, false, true, false]: break; default: break; } 

NON , simplement vous ne pouvez pas.

 SwitchStatement: switch ( Expression ) SwitchBlock 

Le type de l’expression doit être char, byte, short, int, Character, Byte, Short, Integer, Ssortingng ou un type enum (§8.9), ou une erreur de compilation se produit.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11

@ sᴜʀᴇsʜ ᴀᴛᴛᴀ a raison. Mais je voulais append quelque chose. Depuis Java 7, les instructions switch prennent en charge les chaînes, vous pouvez donc faire quelque chose avec cela. C’est vraiment sale et je ne le recommande pas, mais ça marche:

 boolean[] values = new boolean[4]; values[0] = true; values[1] = false; values[2] = false; values[3] = true; switch (Arrays.toSsortingng(values)) { case "[true, false, true, false]": break; case "[false, false, true, false]": break; default: break; } 

Pour ceux qui se soucient de la performance: vous avez raison, ce n’est pas super rapide. Ceci sera compilé dans quelque chose comme ceci:

 Ssortingng temp = Arrays.toSsortingng(values) int hash = temp.hashCode(); switch (hash) { case 0x23fe8da: // Assume this is the hashCode for that // original ssortingng, computed at comstack-time if (temp.equals("[true, false, true, false]")) { } break; case 0x281ddaa: if (temp.equals("[false, false, true, false]")) { } break; default: break; } 

Vous ne pouvez pas activer des tableaux entiers. Mais vous pouvez convertir en bit au désortingment de la lisibilité du switch lui-même:

switch (values[0] + 2 * values[1] + 4 * values[2] + 8 * values[3])

et utilisez des littéraux binarys dans vos instructions de case 0b0101 : le case 0b0101 est le premier.

Essayez cette solution:

  boolean[] values = new boolean[4]; values[0] = true; values[1] = false; values[2] = false; values[3] = true; if (ArrayUtils.isEquals(values, new boolean[] {true, false, true, false})) { ... } else if (ArrayUtils.isEquals(values, new boolean[] {false, false, true, false})) { ... } else { ... } 

Voir les documents ici .

Oui, vous pouvez passer un tableau à un commutateur. Le problème est que je ne parle pas de tableaux Java, mais d’une structure de données.

Un tableau est un arrangement systématique d’objects, généralement en lignes et en colonnes.

Ce que vous essayez de faire est d’implémenter un système qui reconnaît différents indicateurs et, en fonction des indicateurs activés ou désactivés, vous effectuez différentes actions.

Exemple

Une implémentation populaire de ce mécanisme est les permissions de fichiers Linux. Où vous avez rwx comme “tableau de drapeaux”.

Si le tableau entier est vrai, vous verrez rwx , ce qui signifie que vous avez toutes les permissions. Si vous n’êtes pas autorisé à effectuer une action sur un fichier, le tableau entier est faux, vous verrez --- .

la mise en oeuvre

Devinez quoi, vous pouvez penser à des entiers comme des tableaux. Un entier est représenté par un “tableau de bits”.

 001 // 1, if on, set x 010 // 2, if on, set w 100 // 4, if on, set r // putting it all together in a single "array" (integer) 111 // 2^2 + 2^1 + 2^0 = 4 + 2 + 1 = 7 

C’est pourquoi l’autorisation rwx peut être représentée comme un 7

Extrait Java:

 class Flags { public static void main(Ssortingng args[]) { /** * Note the notation "0b", for binary; I'm using it for emphasis. * You could just do: * byte flags = 6; */ byte flags = 0b110; // 6 switch(flags) { case 0: /* do nothing */ break; case 3: /* execute and write */ break; case 6: System.out.println("read and write\n"); break; case 7: /* grant all permissions */ break; default: System.out.println("invalid flag\n"); } } } 

Pour en savoir plus sur l’utilisation d’un format binary, cochez cette question: En Java, puis-je définir une constante entière au format binary?

Performance

  • Économise de la mémoire
  • Vous n’êtes pas obligé de faire des traitements supplémentaires, des commutateurs ou tout autre type de jonglage.

C les programmes qui nécessitent d’être aussi efficaces que possible utilisent ce type de mécanisme; ils utilisent des drapeaux représentés avec des bits uniques.

Non, vous ne pouvez pas, cependant vous pouvez remplacer le code ci-dessus par le code suivant (sale que j’avoue):

 boolean[] values = new boolean[4]; values[0] = true; values[1] = false; values[2] = false; values[3] = true; switch(makeSuitableForSwitch(values)) { case 1010: break; case 10: break; default: break; } private int makeSuitableForSwitch( boolean[] values) { return (values[0]?1:0)*1000+(values[1]?1:0)*100+(values[2]?1:0)*10+(values[3]?1:0); } 

Si vous essayez de déterminer si un ensemble de conditions est vrai, j’utiliserai plutôt des champs binarys.

Par exemple,

 public class HelloWorld { // These are the options that can be set. // They're final so treated as constants. static final int A=1<<0, B=1<<1, C=1<<2, D=1<<3 ; public static void main(String []args) { // Now I set my options to have A=true, B=true, C=true, D=false, effectively int options = A | B | C ; switch( options ) { case (A): System.out.println( "just A" ) ; break ; case (A|B): System.out.println( "A|B" ) ; break ; case (A|B|C): // Final int is what makes this work System.out.println( "A|B|C" ) ; break ; default: System.out.println( "unhandled case" ) ; break ; } } } 

Je calculerais une valeur basée sur la séquence des éléments dans le tableau booléen, c.-à-d. [true, false, true, true] serait évalué à 1011, puis basé sur cette valeur entière, vous pouvez utiliser une instruction switch

La réponse est non. La meilleure explication est d’apprendre à utiliser l’instruction switch .

A partir de JRE 1.7, vous devrez utiliser un hack, je vous recommande:

  • Supposons des values.length <= 64

  • Convertir des valeurs en un long représentant des bitflags

  • Switch contre des nombres magiques hexadécimaux

Java Code Hack:

 if(values.length > 64) throw new IllegalStateException(); long bitflags = 0x0L; for(int i=0; i< values.length; ++i) if(values[i]) bitflags |= 0x01L << i; switch(bitflags) { case 0xEL: // represents [true, true, true, false] break; case 0xAL: // represents [true, false, true, false] break; case 0x2L: // represents [false, false, true, false] break; default: break; } 

Voici une autre approche ne nécessitant ni importations ni bibliothèques:

 boolean[] values = new boolean[4]; values[0] = true; values[1] = false; values[2] = false; values[3] = true; int mask = buildMask(values); if (areEquals(mask, true, false, true, false)) { // ... } else if (areEquals(mask, false, false, true, false)) { // ... } else { // ... } private int buildMask(boolean... values) { int n = 0; for (boolean b : values) { n = (n << 1) | (b ? 1 : 0); } return n; } private boolean areEquals(int mask, boolean... values) { return mask == buildMask(values); } 

Cette réponse n’est pas Java , mais Haxe parce que cela est possible, grâce à la correspondance de modèle et a des résultats intéressants, ce qui pourrait vous être utile pour trouver un commutateur qui fait ce que vous demandez. Les tableaux peuvent correspondre à une longueur fixe.

J’ai créé une démo qui comstack en Javascript et Flash. Vous pouvez voir le js-output dans la colonne de droite.

Démo: http://try.haxe.org/#86314

 class Test { static function main(){ var array=[true,false,true]; var result=switch(array){ case [true,true,false]: "no"; case [true,false,true]: "yes"; default:"??"; } #if js new js.JQuery("body").html(result); #elseif flash trace(result); #end // ouputs: "yes" } } 

C’est le commutateur de sortie, il utilise des commutateurs nesteds. Si vous jouez avec les boîtiers, vous voyez comment la sortie js change pour avoir un commutateur efficace.

 (function () { "use ssortingct"; var Test = function() { }; Test.main = function() { var array = [true,false,true,false]; var result; switch(array.length) { case 4: switch(array[0]) { case true: switch(array[1]) { case false: switch(array[2]) { case true: switch(array[3]) { case false: result = "no"; break; default: result = "??"; } break; default: result = "??"; } break; default: result = "??"; } break; case false: switch(array[1]) { case false: switch(array[2]) { case true: switch(array[3]) { case false: result = "yes"; break; default: result = "??"; } break; default: result = "??"; } break; default: result = "??"; } break; } break; default: result = "??"; } new js.JQuery("body").html(result); }; var js = {}; var q = window.jQuery; js.JQuery = q; Test.main(); })(); 

Un autre motif intéressant que vous pouvez utiliser des traits de soulignement. un motif _ correspond à tout, donc cas _: est égal à défaut, ce qui vous permet de le faire:

 var myArray = [1, 6]; var match = switch(myArray) { case [2, _]: "0"; case [_, 6]: "1"; case []: "2"; case [_, _, _]: "3"; case _: "4"; } trace(match); // 1 

http://haxe.org/manual/pattern_matching#array-matching

Vous pouvez également voir comment Groovy implémente les méthodes isCase () en Java, utilisez une version plus simple qui répond à vos besoins. Il est possible de mettre cela dans une interface et de créer un DSL pour comparer deux objects de votre application.

 return isCase(DefaultTypeTransformation.asCollection(caseValue), switchValue); 

Le code correspondant est indiqué dans les lignes 877 à 982.

@Todor Oui, C’EST POSSIBLE EN JAVA.

 boolean[] values = new boolean[4]; values[0] = true; values[1] = false; values[2] = false; values[3] = true; values = Arrays.toSsortingng(values) switch (values) { case "[true, false, true, false]": break; case "[false, false, true, false]": break; case "[true, false, false, true]": System.out.println("YAAAAAAAAAA GOT IT"); break; default: break; } 

Note: Je ne suis pas un développeur Java, donc la syntaxe de mon code peut être fausse, mais la logique est parfaite. Vous pouvez modifier ma réponse. Ici, j’ai juste essayé de convertir un tableau en un format de chaîne et de le faire correspondre dans le cas d’un commutateur.

J’utiliserais des valeurs int const qui représentent l’état booléen.

Si vous utilisez Java 1.7 ou supérieur, vous pouvez utiliser des littéraux binarys plus lisibles .

 public static final int TRUE_FALSE_TRUE_FALSE = 0b1010; public static final int FALSE_FALSE_TRUE_FALSE = 0b0010; 

pour Java 1.6 et versions ultérieures, utilisez tout autre littéral int, par exemple hex.

 public static final int TRUE_FALSE_TRUE_FALSE = 0xA; public static final int FALSE_FALSE_TRUE_FALSE = 0x2; 

puis créez une méthode qui convertit un tableau booléen en un bit entier. Par exemple

 public static int toIntBitSet(boolean...values){ int bitset = 0; for (boolean value : values) { bitset = (bitset << 1) | (value ? 1 : 0); } return bitset; } 

Enfin, utilisez les constantes dans votre déclaration de commutateur

 boolean[] values = new boolean[]{true, false, true, false}; int bitset = toIntBitSet(values); switch (bitset) { case TRUE_FALSE_TRUE_FALSE: System.out.println(Integer.toBinarySsortingng(bitset)); break; case FALSE_FALSE_TRUE_FALSE: System.out.println(Integer.toBinarySsortingng(bitset)); break; default: break; } 

Une autre approche pourrait consister à utiliser un BitSet Java et un Map correspondant à la logique à exécuter en fonction de la valeur du bitet.

 public static void main(Ssortingng[] args) throws Exception { Map> bitSetMap = new HashMap<>(); bitSetMap.put(bitSetValueOf(true, false, true, false), new TrueFalseTrueFalseCallable()); bitSetMap.put(bitSetValueOf(false, false, true, false), new FalseFalseTrueFalseCallable()); boolean[] values = new boolean[]{true, false, true, false}; BitSet bitset = bitSetValueOf(values); Callable callable = bitSetMap.get(bitset); if (callable == null) { callable = new DefaultCallable(); } Ssortingng result = callable.call(); System.out.println(result); } public static BitSet bitSetValueOf(boolean... values) { BitSet bitSet = new BitSet(); for (int i = 0; i < values.length; i++) { bitSet.set(i, values[i]); } return bitSet; } 

et mettre en œuvre votre logique

 class FalseFalseTrueFalseCallable implements Callable { @Override public Ssortingng call() throws Exception { return "0010"; } } class TrueFalseTrueFalseCallable implements Callable { @Override public Ssortingng call() throws Exception { return "1010"; } } class DefaultCallable implements Callable { @Override public Ssortingng call() throws Exception { return "default value"; } }