我正在尝试做这样的事情,即在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;
}
答案 0 :(得分:73)
@sᴜʀᴇsʜᴀᴛᴛᴀ是对的。但我想补充一些东西。从Java 7开始,switch语句支持Strings,所以你可以用它做点什么。 真的很脏,我不推荐,但这样做有效:
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;
}
对于那些关心表现的人:你是对的,这不是超级快。这将编译成如下:
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;
}
答案 1 :(得分:62)
否,根本就是你不能。
SwitchStatement:
switch ( Expression ) SwitchBlock
Expression的类型必须是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
答案 2 :(得分:50)
您无法打开整个阵列。但是你可以转换成一个位集,代价是switch
本身的一些可读性:
switch (values[0] + 2 * values[1] + 4 * values[2] + 8 * values[3])
并在案例陈述中使用二进制文字:case 0b0101
是您的第一个。
答案 3 :(得分:47)
试试这个解决方案:
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 {
...
}
请参阅文档here。
答案 4 :(得分:22)
是的,您可以将数组传递给交换机。问题在于我不是在谈论Java数组,而是数据结构。
数组是对象的系统排列,通常是行和列。
您要做的是实现一个识别不同标志的系统,并根据打开或关闭的标志执行不同的操作。
示例强>
此类机制的流行实现是Linux文件权限。你有rwx
作为“数组标志”的地方。
如果整个数组都是真的,你会看到rwx
,这意味着你拥有所有权限。如果您不允许对文件执行任何操作,则整个数组都为false,您将看到---
。
<强>实施强>
猜猜是什么,你可以将整数看作数组。整数由“位数组”表示。
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");
}
}
}
要了解有关使用二进制格式的详情,请查看以下问题:In Java, can I define an integer constant in binary format?
<强>性能强>
要求尽可能高效的C程序使用这种机制;它们使用以单比特表示的标志。
答案 5 :(得分:21)
不,你不能,但是你可以用以下(脏我承认)代码替换上面的代码:
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);
}
答案 6 :(得分:9)
如果您正在尝试确定一组条件是否为真,那么我会使用按位字段。
例如,
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 ;
}
}
}
答案 7 :(得分:6)
我根据布尔数组中的元素序列计算一个值,即[true, false, true, true]
将计算为1011,然后根据此整数值,您可以使用switch语句。
答案 8 :(得分:2)
答案是否定的。最好的解释是学习如何使用the switch statement。
答案 9 :(得分:2)
从JRE 1.7开始,你需要使用hack,我建议:
假设values.length <= 64
将值转换为代表bitflags的long
Switch
针对十六进制magic numbers
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;
}
答案 10 :(得分:1)
这是另一种不需要导入或库的方法:
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);
}
答案 11 :(得分:1)
这个答案是不是Java ,而是Haxe,因为它有可能,因为模式匹配并且有一个有趣的输出,这可能对你找到一个满足你要求的开关很有用对于。数组可以固定长度匹配。
我创建了一个编译为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"
}
}
这是输出的开关,它使用嵌套开关。如果您使用这些案例,您会看到js-ouput如何更改以实现高效切换。
(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
答案 12 :(得分:1)
您还可以了解Groovy如何在Java中实现isCase()方法,使用更符合您需求的更简单版本。可以将它放在一个接口中并创建一个DSL来比较应用程序中的任何两个对象。
return isCase(DefaultTypeTransformation.asCollection(caseValue), switchValue);
中
答案 13 :(得分:1)
@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开发人员,所以我的代码语法可能是错误的,但逻辑是完美的。你可以编辑我的答案。在这里,我只是尝试将数组转换为字符串格式,然后匹配switch case。
答案 14 :(得分:0)
我会使用表示布尔状态的常量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文字,例如十六进制
public static final int TRUE_FALSE_TRUE_FALSE = 0xA;
public static final int FALSE_FALSE_TRUE_FALSE = 0x2;
然后创建一个将布尔数组转换为整数位集的方法。 E.g。
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
和Map
映射到应根据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";
}
}