Java 在 switch 中使用数组作为 case 语句

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20659979/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 03:23:35  来源:igfitidea点击:

Use an array as a case statement in switch

javaarraysswitch-statement

提问by Todor Grudev

I am trying to do something like this, i.e., use an array in a switch statement. Is it possible in Java? If it isn't, please explain a possible solution.

我正在尝试做这样的事情,即在 switch 语句中使用数组。在Java中可能吗?如果不是,请说明可能的解决方案。

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

采纳答案by Suresh Atta

NO, simply you cannot.

,你不能。

SwitchStatement:
    switch ( Expression ) SwitchBlock

The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, String, or an enum type (§8.9), or a compile-time error occurs.

表达式的类型必须是 char、byte、short、int、Character、Byte、Short、Integer、String 或枚举类型(第 8.9 节),否则会发生编译时错误。

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

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

回答by Sergi

The answer is NO. The best explain is learn how to use the switch statement.

答案是不。最好的解释是学习如何使用switch 语句

回答by Alex

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

See docs here.

请参阅此处的文档。

回答by Adam Siemion

No, you cannot, however you can replace the above with the following (dirty I admit) code:

不,你不能,但是你可以用以下(我承认脏)代码替换上面的代码:

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

回答by Juvanis

I'd compute a value based on the sequence of the elements in the boolean array, i.e. [true, false, true, true]would evaluate to 1011 and then based on this integer value you can use switch statement.

我会根据布尔数组中元素的序列计算一个值,即[true, false, true, true]计算结果为 1011,然后根据这个整数值,您可以使用 switch 语句。

回答by Bathsheba

You can't switch on whole arrays. But you couldconvert to a bit set at the expense of some readability of the switchitself:

您无法打开整个阵列。但是您可以以牺牲switch自身的一些可读性为代价转换为一个位集:

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

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

and use binary literalsin your case statements: case 0b0101is your first one.

并在您的 case 语句中使用二进制文字case 0b0101是您的第一个。

回答by Martijn Courteaux

@s???s? ???? is right. But I wanted to add something. Since Java 7, switch statements support Strings, so you could do something with that. It is really dirtyand I do not recommend, but this works:

@s???s????是对的。但我想补充一点。从 Java 7 开始,switch 语句支持字符串,所以你可以用它做一些事情。它真的很脏,我不推荐,但这有效:

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


For those concerned about performance: you are right, this is not super fast. This will be compiled into something like this:

对于那些关心性能的人:你是对的,这不是超级快。这将被编译成这样的:

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

回答by givanse

Yes, you can pass an array to a switch. The catch is that I'm not talking about Java arrays, but a data structure.

是的,您可以将数组传递给交换机。问题是我不是在谈论 Java 数组,而是在谈论一种数据结构。

An array is a systematic arrangement of objects, usually in rows and columns.

数组是对象的系统排列,通常按行和列排列。

What you are trying to do is implement a system that recognizes different flags and depending on the flags that are turned on or off you take different actions.

您要做的是实现一个识别不同标志的系统,并根据打开或关闭的标志采取不同的操作。

Example

例子

A popular implementation of such mechanism is Linux file permissions. Where you have rwxas the "array of flags".

这种机制的一个流行实现是 Linux 文件权限。您拥有rwx“标志数组”的位置。

If the whole array is true, you'll see rwx, which means that you have all the permissions. If you are not allowed to perform any action on a file, the whole array is false, you'll see ---.

如果整个数组为真,您将看到rwx,这意味着您拥有所有权限。如果不允许您对文件执行任何操作,则整个数组为 false,您将看到---.

Implementation

执行

Guess what, you can think of integers as arrays. An integer is represented by an "array of 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

That is why the permission rwxcan be represented as a 7

这就是为什么rwx可以将权限表示为7

Java snippet:

Java片段:

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

To know more about using a binary format, check this question: In Java, can I define an integer constant in binary format?

要了解有关使用二进制格式的更多信息,请查看以下问题:在 Java 中,我可以定义二进制格式的整数常量吗?

Performance

表现

  • Saves memory
  • You don't have to do extra processing, switches or any other type of juggling.
  • 节省内存
  • 您不必进行额外的处理、切换或任何其他类型的杂耍。

C programs that require to be as efficient as possible use this type of mechanism; they use flags represented with single bits.

需要尽可能高效的 C 程序使用这种类型的机制;他们使用用单个位表示的标志。

回答by bobobobo

If you're trying to determine if a set of conditionsis true, I'd use bitwise fields instead.

如果您要确定一组条件是否为真,我会改用按位字段。

For example,

例如,

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

回答by Stephan

Here is another approach requiring no imports nor libraries:

这是另一种不需要导入或库的方法:

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