Ich versuche so etwas zu tun, d. H. 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;
}
NEIN, das geht einfach nicht.
SwitchStatement:
switch ( Expression ) SwitchBlock
Der Typ des Ausdrucks muss char, Byte, short, int, Character, Byte, short, Integer, String oder ein Aufzählungstyp (§8.9) sein. Andernfalls tritt ein Fehler beim Kompilieren auf.
http://docs.Oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11
@ sᴜʀᴇsʜ ᴀᴛᴛᴀ ist richtig. Aber ich wollte etwas hinzufügen. Seit Java 7 unterstützen switch-Anweisungen Strings, damit könnte man etwas unternehmen. Es ist wirklich schmutzig und ich empfehle es 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 besonders schnell. Dies wird wie folgt 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;
}
Sie können nicht ganze Arrays einschalten. Aber Sie könnten auf Kosten der Lesbarkeit von switch
selbst in ein gesetztes Bit konvertieren:
switch (values[0] + 2 * values[1] + 4 * values[2] + 8 * values[3])
und benutze binäre Literale in deinen case-Anweisungen: case 0b0101
ist dein erster.
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 docs hier .
Ja, Sie können ein Array an einen Switch übergeben. Der Haken ist, dass es nicht um Java-Arrays geht, sondern um eine Datenstruktur.
Ein Array ist eine systematische Anordnung von Objekten, normalerweise in Zeilen und Spalten.
Sie möchten ein System implementieren, das verschiedene Flags erkennt, und je nach aktivierten oder deaktivierten Flags führen Sie verschiedene Aktionen aus.
Beispiel
Eine beliebte Implementierung eines solchen Mechanismus sind Linux-Dateiberechtigungen. Wo haben Sie rwx
als "Array von Flags".
Wenn das gesamte Array true ist, wird rwx
angezeigt, dh Sie verfügen über alle Berechtigungen. Wenn Sie keine Aktion für eine Datei ausführen dürfen, ist das gesamte Array "false" und es wird ---
angezeigt.
Implementierung
Weißt du was, du kannst ganze Zahlen als Arrays sehen. Eine ganze Zahl 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
Aus diesem Grund kann die Berechtigung rwx
als 7
dargestellt werden.
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?
Leistung
C-Programme, die so effizient wie möglich sein müssen, verwenden diesen Mechanismus. Sie verwenden Flags, die mit einzelnen Bits dargestellt werden.
Nein, das ist nicht möglich. Sie können den obigen Code jedoch durch folgenden 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);
}
Wenn Sie feststellen wollen, ob ein Satz von Bedingungen wahr ist, würde ich 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 ;
}
}
}
Ich würde einen Wert basierend auf der Reihenfolge der Elemente im booleschen Array berechnen, d. H. [true, false, true, true]
würde den Wert 1011 auswerten, und basierend auf diesem Integerwert können Sie die switch-Anweisung verwenden.
Die Antwort ist nein. Die beste Erklärung ist, wie man die switch-Anweisung verwendet.
Ab JRE 1.7 müssen Sie einen Hack verwenden. Ich empfehle:
values.length <= 64
annehmen
Konvertieren Sie Werte in eine long
, die Bitflags darstellt
Switch
gegen hexadezimal magische Zahlen
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;
}
Hier ist ein anderer Ansatz, der weder Import 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);
}
Diese Antwort ist nicht Java, aber Haxe, weil es dank Pattern Matching möglich ist und interessante Ausgaben bietet, die für Sie nützlich sein könnten, um einen Switch zu finden, der das tut, was Sie wünschen. Arrays können auf fester Länge abgeglichen werden.
Ich habe eine Demo erstellt, die zu Javascript und Flash kompiliert wird. Die js-Ausgabe sehen Sie in der rechten Spalte.
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 Schalter, er verwendet verschachtelte Schalter. Wenn Sie mit den Fällen spielen, sehen Sie, wie sich das js-outout ändert, um einen effizienten Switch zu erhalten.
(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 Unterstriche verwenden können. Ein _-Muster stimmt mit irgendetwas überein, daher ist Fall _: gleich default, wodurch 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
@Todor Ja, DIESES IS MÖGLICH IN Java.
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. Die Logik ist jedoch perfekt. Sie können meine Antwort bearbeiten. Hier habe ich gerade versucht, das Array in ein String-Format zu konvertieren und dann im Switch-Case zu finden.
Sie können auch einen Blick darauf werfen, 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 ein DSL zu erstellen, um zwei beliebige Objekte in Ihrer Anwendung zu vergleichen.
return isCase(DefaultTypeTransformation.asCollection(caseValue), switchValue);
Der entsprechende Code wird in Zeilen 877 bis Zeilen 982 behandelt.
Ich würde konstante int-Werte verwenden, die den booleschen Zustand darstellen.
Wenn Sie Java 1.7 oder höher verwenden, können Sie binäre Literale verwenden, die lesbarer sind.
public static final int TRUE_FALSE_TRUE_FALSE = 0b1010;
public static final int FALSE_FALSE_TRUE_FALSE = 0b0010;
für Java 1.6 und darunter alle anderen Int-Literale verwenden, z. verhexen
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 die Verwendung von Java BitSet
und Map
sein, die der Logik zugeordnet sind, 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 implementiere deine 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";
}
}