在交换机中使用数组作为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
您还可以看看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"; } }