Ich versuche so etwas zu tun, dh ein Array in einer switch-Anweisung zu verwenden. Ist es in Java möglich? Ist dies nicht der Fall, erläutern Sie bitte eine mögliche Lösung.
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;
}
java
arrays
switch-statement
Todor Grudev
quelle
quelle
boolean
Array abhängen sollte . Vielleicht könnte eine Klasse diese Daten besser mit Methoden enthalten, die mehr Semantik haben (und einfacher zu testen sind)? Wie Sie es geschrieben haben, sieht es aus wie ein zukünftiger Alptraum für die Wartung.Antworten:
NEIN , einfach kannst du nicht.
SwitchStatement: switch ( Expression ) SwitchBlock
http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11
quelle
@ sᴜʀᴇsʜ ᴀᴛᴛᴀ ist richtig. Aber ich wollte etwas hinzufügen. Seit Java 7 unterstützen switch-Anweisungen Strings, sodass Sie damit etwas anfangen können. Es ist wirklich schmutzig und ich empfehle nicht, aber das funktioniert:
boolean[] values = new boolean[4]; values[0] = true; values[1] = false; values[2] = false; values[3] = true; switch (Arrays.toString(values)) { case "[true, false, true, false]": break; case "[false, false, true, false]": break; default: break; }
Für diejenigen, die sich Gedanken über die Leistung machen: Sie haben Recht, das ist nicht super schnell. Dies wird in etwa so zusammengestellt:
String temp = Arrays.toString(values) int hash = temp.hashCode(); switch (hash) { case 0x23fe8da: // Assume this is the hashCode for that // original string, computed at compile-time if (temp.equals("[true, false, true, false]")) { } break; case 0x281ddaa: if (temp.equals("[false, false, true, false]")) { } break; default: break; }
quelle
toString
int
- Sie konvertieren jedoch in Zeichenfolgen und vergleichen diese . In Java .Sie können nicht ganze Arrays einschalten. Sie können jedoch auf Kosten der Lesbarkeit
switch
selbst in ein Bit konvertieren :switch (values[0] + 2 * values[1] + 4 * values[2] + 8 * values[3])
und verwenden Sie binäre Literale in Ihren case-Anweisungen:
case 0b0101
ist Ihre erste.quelle
int switchVal = 0; for (int i = 0; i < values.length(); i++) { switchVal += values[i] ? (2 << i) : 0; }
und dann dieswitchVal
Variable einschalten .[true, false, true, false]
in eine Reihe von Bits1010
, die bearbeitet werden könnenswitch
, oder? Auf jeden Fall der Weg zu IMO.Versuchen Sie diese Lösung:
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 { ... }
Siehe Dokumente hier .
quelle
isEquals
?java.util.Arrays.equals(arr1,arr2)
aus dem JDK.isEqual
soverb adjective
oder soverb noun
stattverb verb
. Persönlich bevorzuge ich nuradjective
boolesche Funktionen undverb
Prozeduren, die den Status ändern.Ja, Sie können ein Array an einen Switch übergeben. Der Haken ist, dass ich nicht über Java-Arrays spreche, sondern über eine Datenstruktur.
Sie versuchen, ein System zu implementieren, das unterschiedliche Flags erkennt, und abhängig von den ein- oder ausgeschalteten Flags führen Sie unterschiedliche Aktionen aus.
Beispiel
Eine beliebte Implementierung eines solchen Mechanismus sind Linux-Dateiberechtigungen. Wo Sie
rwx
als "Array von Flags" haben.Wenn das gesamte Array wahr ist, werden Sie sehen
rwx
, was bedeutet, dass Sie über alle Berechtigungen verfügen. Wenn Sie keine Aktion für eine Datei ausführen dürfen, ist das gesamte Array falsch---
.Implementierung
Ratet mal, Sie können sich ganze Zahlen als Arrays vorstellen. Eine Ganzzahl wird durch ein "Array von Bits" dargestellt.
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
Deshalb
rwx
kann die Erlaubnis als dargestellt werden7
Java-Snippet:
class Flags { public static void main(String 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"); } } }
Um mehr über die Verwendung eines Binärformats zu erfahren, überprüfen Sie diese Frage: Kann ich in Java eine Ganzzahlkonstante im Binärformat definieren?
Performance
C-Programme, die so effizient wie möglich sein müssen, verwenden diese Art von Mechanismus. Sie verwenden Flags, die mit einzelnen Bits dargestellt werden.
quelle
Nein, das können Sie nicht, aber Sie können das Obige durch den folgenden (ich gebe zu) schmutzigen Code ersetzen:
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); }
quelle
switch
Anweisung.0010
wird als oktal interpretiert ...private
;) Auch ist es keine gute Idee,return int
da dies bei großen Arrays überlaufen kann.(values[0]?1:0)*1000
wenn du kannstvalues[0]?1000:0
?Wenn Sie feststellen möchten, ob eine Reihe von Bedingungen erfüllt ist, verwende ich stattdessen bitweise Felder.
Zum Beispiel,
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 ; } } }
quelle
Ich würde einen Wert basierend auf der Reihenfolge der Elemente im booleschen Array berechnen, dh
[true, false, true, true]
1011 auswerten und dann basierend auf diesem ganzzahligen Wert die switch-Anweisung verwenden.quelle
Die Antwort ist nein. Am besten lernen Sie, wie Sie die switch-Anweisung verwenden .
quelle
Ab JRE 1.7 müssen Sie einen Hack verwenden. Ich empfehle:
Annehmen
values.length <= 64
Konvertieren Sie Werte in
long
darstellende BitflagsSwitch
gegen hexadezimale magische ZahlenJava 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; }
quelle
Ich habe eine Demo erstellt, die in Javascript und Flash kompiliert werden kann. Sie können die js-Ausgabe in der rechten Spalte sehen.
Demo: 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" } }
Dies ist der ausgegebene Switch, der verschachtelte Switches verwendet. Wenn Sie mit den Fällen spielen, sehen Sie, wie sich die js-Ausgabe ändert, um einen effizienten Schalter zu haben.
(function () { "use strict"; 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(); })();
Ein weiteres interessantes Muster, das Sie mit Unterstrichen versehen können. Ein _-Muster stimmt mit allem überein, daher entspricht case _: dem Standardwert, sodass Sie Folgendes tun können:
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
quelle
Hier ist ein weiterer Ansatz, der weder Importe noch Bibliotheken erfordert:
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); }
quelle
Sie können sich auch ansehen, wie Groovy die isCase () -Methoden in Java implementiert. Verwenden Sie eine einfachere Version, die Ihren Anforderungen entspricht. Es ist möglich, dies in eine Schnittstelle einzufügen und eine DSL zu erstellen, um zwei beliebige Objekte in Ihrer Anwendung zu vergleichen.
return isCase(DefaultTypeTransformation.asCollection(caseValue), switchValue);
Der relevante Code wird in den Zeilen 877 bis 982 behandelt
quelle
@Todor Ja, das ist in Java möglich.
boolean[] values = new boolean[4]; values[0] = true; values[1] = false; values[2] = false; values[3] = true; values = Arrays.toString(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; }
Hinweis: Ich bin kein Java-Entwickler, daher kann meine Codesyntax falsch sein, aber die Logik ist perfekt. Sie können meine Antwort bearbeiten. Hier habe ich nur versucht, das Array in das String-Format zu konvertieren und es dann im Switch-Fall abzugleichen.
quelle
Ich würde konstante int-Werte verwenden, die den booleschen Zustand darstellen.
Wenn Sie Java 1.7 oder höher verwenden, können Sie besser lesbare Binärliterale verwenden .
public static final int TRUE_FALSE_TRUE_FALSE = 0b1010; public static final int FALSE_FALSE_TRUE_FALSE = 0b0010;
Verwenden Sie für Java 1.6 und niedriger andere int-Literale, z. B. hex
public static final int TRUE_FALSE_TRUE_FALSE = 0xA; public static final int FALSE_FALSE_TRUE_FALSE = 0x2;
Erstellen Sie dann eine Methode, die ein boolesches Array in ein ganzzahliges Bitset konvertiert. Z.B
public static int toIntBitSet(boolean...values){ int bitset = 0; for (boolean value : values) { bitset = (bitset << 1) | (value ? 1 : 0); } return bitset; }
Verwenden Sie schließlich die Konstanten in Ihrer switch-Anweisung
boolean[] values = new boolean[]{true, false, true, false}; int bitset = toIntBitSet(values); switch (bitset) { case TRUE_FALSE_TRUE_FALSE: System.out.println(Integer.toBinaryString(bitset)); break; case FALSE_FALSE_TRUE_FALSE: System.out.println(Integer.toBinaryString(bitset)); break; default: break; }
Ein anderer Ansatz könnte darin bestehen, ein Java
BitSet
und ein Java zu verwendenMap
, das der Logik zugeordnet ist, die abhängig vom Wert des Bitsets ausgeführt werden soll.public static void main(String[] args) throws Exception { Map<BitSet, Callable<String>> 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<String> callable = bitSetMap.get(bitset); if (callable == null) { callable = new DefaultCallable(); } String 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; }
und implementieren Sie Ihre Logik
class FalseFalseTrueFalseCallable implements Callable<String> { @Override public String call() throws Exception { return "0010"; } } class TrueFalseTrueFalseCallable implements Callable<String> { @Override public String call() throws Exception { return "1010"; } } class DefaultCallable implements Callable<String> { @Override public String call() throws Exception { return "default value"; } }
quelle