Verwenden Sie ein Array als case-Anweisung in switch
Lesezeit: 7 Minuten
Todor Grudev
Ich versuche, so etwas zu tun, dh ein Array in einer Switch-Anweisung zu verwenden. Ist es in Java möglich? Wenn dies nicht der Fall ist, erläutern Sie bitte eine mögliche Lösung.
Ich denke, am besten ist es, eine if-Anweisung zu verwenden und den Schalter zu vermeiden
– Mukul Goel
18. Dezember 2013 um 13:53 Uhr
Ich denke, Sie sollten sich fragen, warum Ihre Ausführung von a abhängen sollte boolean Reihe. 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 Wartungsalptraum.
– Eric Wilson
18. Dezember 2013 um 13:56 Uhr
Verwenden Sie eine Schleife, um Bits auf einem int basierend auf dem Array-Index zu setzen, und schalten Sie das aus.
– oktal9
18. Dezember 2013 um 15:49 Uhr
Was Sie wollen, heißt “Musterabgleich”, aber Sie können es nicht in Java tun.
– Ing
18. Dezember 2013 um 16:07 Uhr
Es hört sich so an, als ob Sie versuchen, Bit-Flags zu implementieren – siehe diese Frage: Implementieren eines Bitfelds mit Java-Enumerationen
– T. Kiley
18. Dezember 2013 um 20:13 Uhr
Martin Courteaux
@sᴜʀᴇsʜ ᴀᴛᴛᴀ hat Recht. Aber ich wollte noch etwas hinzufügen. Seit Java 7 unterstützen Switch-Anweisungen Strings, also könnte man damit etwas anfangen. Es ist wirklich dreckig und ich empfehle nicht, aber das funktioniert:
Für diejenigen, die sich Sorgen um die Leistung machen: Sie haben Recht, das ist nicht superschnell. Dies wird in etwa so kompiliert:
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;
}
Ich bin ziemlich neutral +-1. Es wäre sehr langsam. Ich dachte auch nicht, dass du das tun solltest analysierentoString Ausgabe ein irgendein Weg.
– Bathseba
18. Dezember 2013 um 14:04 Uhr
Kreativ und schrecklich zugleich. +1
– David
18. Dezember 2013 um 14:05 Uhr
Zu eingeschränkt auf die Größe des Arrays, wenn sich die Größe des Arrays ändert, was für ein Durcheinander ist es, es zu verwalten.
– Jonathan Drapeau
18. Dezember 2013 um 14:08 Uhr
Da ist diese blasierte Einstellung zur Leistung. Diese Art von Problem ist sehr häufig gelöst mit Setzen von Bits in einem int — dennoch wandelst du um und vergleichst Saiten. Auf Java.
– bobobobo
19. Dezember 2013 um 13:46 Uhr
@bobobobo: Du hast recht. Ich werde das niemals für mich selbst schreiben. Dies war nur ein lustiges Stück Code, das dem, was das OP wollte, sehr nahe kommt. Ich weiß, dass das schrecklich ist, vertrau mir 🙂
Der Typ des Ausdrucks muss char, byte, short, int, Character, Byte, Short, Integer, String oder ein Aufzählungstyp (§8.9) sein, oder es tritt ein Kompilierungsfehler auf.
Dies ist meiner Meinung nach richtig, obwohl einige gute Bemühungen in den anderen Antworten für eine gute Lösung erforderlich sind.
– Codeflüsterer
18. Dezember 2013 um 19:22 Uhr
Ehrlich gesagt ist dies die beste Antwort. Ich bin mir nicht sicher, ob die Art von Gymnastik, die erforderlich ist, um das ursprüngliche Problem zum Laufen zu bringen, gefördert werden sollte.
– Nicht ich
18. Dezember 2013 um 22:46 Uhr
Das ist wirklich alt und ich kann mich nicht einmal erinnern, was das ursprüngliche Problem war, aber wenn ich auf den Code zurückblicke, scheint es, dass ich eine schlechte architektonische Entscheidung getroffen habe. Deshalb denke ich, dass dies die richtige Antwort ist – es ist eher ein Signal dafür, etwas falsch zu machen, als eine Lösung zu finden.
– Todor Grudev
31. März 2017 um 8:53 Uhr
Bathseba
Sie können nicht ganze Arrays einschalten. Aber du könnte Konvertieren Sie auf Kosten einer gewissen Lesbarkeit der in ein Bit-Set switch selbst:
und verwenden binäre Literale in Ihrem Fall Aussagen: case 0b0101 ist deine erste.
Wow, das ist sicherlich möglich, aber ist das eine gute Lösung für das eigentliche Problem?
– Eric Wilson
18. Dezember 2013 um 13:58 Uhr
Um dies erweiterbar zu machen, würde ich es in eine Schleife einfügen: int switchVal = 0; for (int i = 0; i < values.length(); i++) { switchVal += values[i] ? (2 << i) : 0; } und dann einschalten switchVal Variable.
– Darrel Hoffmann
18. Dezember 2013 um 15:47 Uhr
Und um den Schalter lesbarer/aussagekräftiger zu machen, sollten Sie erwägen, jedes dieser binären Literale zu einer sinnvollen Konstante zu machen, sodass Sie Konstanten und keine binären Literale einschalten.
– rrauenza
18. Dezember 2013 um 19:21 Uhr
Dies ist im Grunde eine Konvertierung [true, false, true, false] zur Bitfolge 1010welches sein kann switched auf, nicht wahr? Definitiv der richtige Weg IMO.
– Iskata
18. Dezember 2013 um 21:33 Uhr
Ich wollte ein binäres Beispiel mit Lambda in Java SE 8 zeigen, war mir aber nicht sicher, ob ich dafür geflammt werden würde. Ich warte bis März.
– Ialexander
18. Dezember 2013 um 23:29 Uhr
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 {
...
}
Ja, Sie können ein Array an einen Switch übergeben. Der Haken an der Sache ist, dass ich hier nicht von Java-Arrays spreche, sondern von einer Datenstruktur.
Ein Array ist eine systematische Anordnung von Objekten, normalerweise in Zeilen und Spalten.
Sie versuchen, ein System zu implementieren, das verschiedene Flags erkennt, und abhängig von den aktivierten oder deaktivierten Flags unterschiedliche Aktionen ausführen.
Beispiel
Eine beliebte Implementierung eines solchen Mechanismus sind Linux-Dateiberechtigungen. Wo du hast rwx als “Array of Flags”.
Wenn das ganze Array wahr ist, werden Sie sehen rwx, was bedeutet, dass Sie alle Berechtigungen haben. Wenn Sie keine Aktion für eine Datei ausführen dürfen, ist das gesamte Array falsch, wie Sie sehen werden ---.
Implementierung
Stellen Sie sich vor, 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 die Erlaubnis rwx kann als dargestellt werden 7
Java-Schnipsel:
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?
Leistung
Spart Speicher
Sie müssen keine zusätzliche Verarbeitung, Schalter oder andere Art von Jonglieren durchführen.
C-Programme, die so effizient wie möglich sein müssen, verwenden diese Art von Mechanismus; Sie verwenden Flags, die durch einzelne Bits dargestellt werden.
Nein, das können Sie nicht, aber Sie können das obige durch den folgenden (schmutzigen, ich gebe zu) 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);
}
bobobobo
Wenn Sie versuchen festzustellen, ob a Reihe von Bedingungen stimmt, ich würde stattdessen bitweise Felder verwenden.
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 ;
}
}
}
12045800cookie-checkVerwenden Sie ein Array als case-Anweisung in switchyes
Ich denke, am besten ist es, eine if-Anweisung zu verwenden und den Schalter zu vermeiden
– Mukul Goel
18. Dezember 2013 um 13:53 Uhr
Ich denke, Sie sollten sich fragen, warum Ihre Ausführung von a abhängen sollte
boolean
Reihe. 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 Wartungsalptraum.– Eric Wilson
18. Dezember 2013 um 13:56 Uhr
Verwenden Sie eine Schleife, um Bits auf einem int basierend auf dem Array-Index zu setzen, und schalten Sie das aus.
– oktal9
18. Dezember 2013 um 15:49 Uhr
Was Sie wollen, heißt “Musterabgleich”, aber Sie können es nicht in Java tun.
– Ing
18. Dezember 2013 um 16:07 Uhr
Es hört sich so an, als ob Sie versuchen, Bit-Flags zu implementieren – siehe diese Frage: Implementieren eines Bitfelds mit Java-Enumerationen
– T. Kiley
18. Dezember 2013 um 20:13 Uhr