Verwenden Sie ein Array als case-Anweisung in switch

Lesezeit: 7 Minuten

Benutzer-Avatar
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.

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;
}

  • 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

Benutzer-Avatar
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:

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 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 analysieren toString 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 🙂

    – Martin Courteaux

    25. Dezember 2013 um 19:10 Uhr

NEINeinfach kannst du 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, oder es tritt ein Kompilierungsfehler auf.

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

  • 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

Benutzer-Avatar
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:

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

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 {
    ...
    }

Siehe Dokumente hier.

Benutzer-Avatar
Geschenk

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);
}

Benutzer-Avatar
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 ;
    }
  }
}

1204580cookie-checkVerwenden Sie ein Array als case-Anweisung in switch

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy