在交换机中使用数组作为case语句

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

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

,只是你不能。

 SwitchStatement: switch ( Expression ) SwitchBlock 

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

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

@sᴜʀᴇsʜᴀᴛᴛᴀ是对的。 但我想添加一些东西。 从Java 7开始,switch语句支持Strings,所以你可以用它来做一些事情。 这真的很脏 ,我不build议,但是这个工程:

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

对于那些关心performance的人来说:你是对的,这不是超快的。 这将被编译成这样的东西:

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

你不能切换整个数组。 但是你可以转换成一些设置,而牺牲switch本身的一些可读性:

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

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

试试这个解决scheme

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

在这里看到文档。

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

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

你要做的是实现一个系统,它可以识别不同的标志,并根据打开或closures的标志采取不同的操作。

这种机制的一个stream行的实现是Linux文件许可。 你把rwx作为“数组标志”。

如果整个数组是真的,你会看到rwx ,这意味着你有所有的权限。 如果你不被允许在一个文件上执行任何操作,整个数组是错误的,你会看到---

履行

猜猜看,你可以把整数看作数组。 一个整数由一个“位数组”表示。

 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 

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

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

要了解更多关于使用二进制格式,请检查以下问题: 在Java中,我可以定义一个二进制格式的整型常量吗?

性能

  • 节省内存
  • 你不必做额外的处理,开关或任何其他types的杂耍。

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

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

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

如果你试图确定一组条件是否为真,我会使用按位字段。

例如,

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

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

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

从JRE 1.7开始,你将需要使用黑客,我build议:

  • 假设values.length <= 64

  • 将值转换为long表示位标志

  • Switch为hex幻数

Java代码黑客:

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

这是另一种不需要import和库的方法:

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

这个答案不是Java ,而是Haxe,因为它是可能的,这要归功于模式匹配,并且有有趣的输出,这可能对你find一个你所要求的开关很有用。 数组可以固定长度匹配。

我创build了一个编译为Javascript和Flash的演示。 你可以在右栏看到js-output。

演示: 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" } } 

这是输出开关,它使用嵌套开关。 如果你玩的情况下,你看到如何改变输出有一个高效的开关。

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

另一个有趣的模式,你可以使用下划线。 一个_模式匹配任何东西,所以case _:等于默认,这使得你能够做到这一点:

 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

您还可以看看Groovy如何在Java中实现isCase()方法,使用更简单的版本来满足您的需求。 可以将它放在一个接口中,并创build一个DSL来比较应用程序中的任何两个对象。

 return isCase(DefaultTypeTransformation.asCollection(caseValue), switchValue); 

第877 行到第982 行涵盖了相关的代码

@Todor 是的,这是在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; } 

注:我不是一个Java开发人员,所以我的代码语法可能是错误的,但逻辑是完美的。 你可以编辑我的答案。 在这里,我只是试图将数组转换为string格式,然后在开关情况下匹配。

我将使用表示布尔状态的常量int值。

如果您使用Java 1.7或更高版本,则可以使用更具可读性的二进制文字。

 public static final int TRUE_FALSE_TRUE_FALSE = 0b1010; public static final int FALSE_FALSE_TRUE_FALSE = 0b0010; 

对于Java 1.6及更低版本,使用其他任何int文字,例如hex

 public static final int TRUE_FALSE_TRUE_FALSE = 0xA; public static final int FALSE_FALSE_TRUE_FALSE = 0x2; 

然后创build一个将布尔数组转换为整数位集的方法。 例如

 public static int toIntBitSet(boolean...values){ int bitset = 0; for (boolean value : values) { bitset = (bitset << 1) | (value ? 1 : 0); } return bitset; } 

最后在switch语句中使用常量

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

另一种方法可能是使用一个java BitSet和一个映射到应该执行的逻辑取决于bitset的值的映射。

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

并执行你的逻辑

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