在每种情况下使用带有值范围的 switch 语句?

在 Java 中,是否可以编写一个 switch 语句,其中每个 case 包含多个值?例如(虽然下面的代码显然不能工作) :

switch (num) {
case 1 .. 5:
System.out.println("testing case 1 to 5");
break;
case 6 .. 10:
System.out.println("testing case 6 to 10");
break;
}

我认为这可以在 Objective C 中完成,在 Java 中有类似的东西吗?或者我应该只使用 ifelse if语句代替?

222829 次浏览

The closest you can get to that kind of behavior with switch statements is

switch (num) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("1 through 5");
break;
case 6:
case 7:
case 8:
case 9:
case 10:
System.out.println("6 through 10");
break;
}

Use if statements.

No you can't do that. The best you can do is that

case 1:
case 2:
case 3:
case 4:
case 5:
System.Out.Println("testing case 1 to 5");
break;

I don't think you can do that in Java. Best bet is to just put the code in the last case of the range.

switch (num) {
case 1: case 2: case 3: case 4: case 5:
System.Out.Println("testing case 1 to 5");
break;
case 6: case 7: case 8: case 9: case 10:
System.Out.Println("testing case 6 to 10");
break;
default:
//
}

It's possible to group several conditions in the same case statement using the mechanism of fall through allowed by switch statements, it's mentioned in the Java tutorial and fully specified in section §14.11. The switch Statement of the Java Language Specification.

The following snippet of code was taken from an example in the tutorial, it calculates the number of days in each month (numbered from month 1 to month 12):

switch (month) {
case 1: case 3: case 5:
case 7: case 8: case 10:
case 12:
numDays = 31;
break;
case 4: case 6:
case 9: case 11:
numDays = 30;
break;
case 2:
if (((year % 4 == 0) &&
!(year % 100 == 0))
|| (year % 400 == 0))
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}

As you can see, for covering a range of values in a single case statement the only alternative is to list each of the possible values individually, one after the other. As an additional example, here's how to implement the pseudocode in the question:

switch(num) {
case 1: case 2: case 3: case 4: case 5:
System.out.println("testing case 1 to 5");
break;
case 6: case 7: case 8: case 9: case 10:
System.out.println("testing case 6 to 10");
break;
}

Java has nothing of that sort. Why not just do the following?

public static boolean isBetween(int x, int lower, int upper) {
return lower <= x && x <= upper;
}


if (isBetween(num, 1, 5)) {
System.out.println("testing case 1 to 5");
} else if (isBetween(num, 6, 10)) {
System.out.println("testing case 6 to 10");
}

other alternative is using math operation by dividing it, for example:

switch ((int) num/10) {
case 1:
System.out.println("10-19");
break;
case 2:
System.out.println("20-29");
break;
case 3:
System.out.println("30-39");
break;
case 4:
System.out.println("40-49");
break;
default:
break;
}

But, as you can see this can only be used when the range is fixed in each case.

You could use an enum to represent your ranges,

public static enum IntRange {
ONE_TO_FIVE, SIX_TO_TEN;
public boolean isInRange(int v) {
switch (this) {
case ONE_TO_FIVE:
return (v >= 1 && v <= 5);
case SIX_TO_TEN:
return (v >= 6 && v <= 10);
}
return false;
}


public static IntRange getValue(int v) {
if (v >= 1 && v <= 5) {
return ONE_TO_FIVE;
} else if (v >= 6 && v <= 10) {
return SIX_TO_TEN;
}
return null;
}
}

@missingfaktor 's answer is indeed correct but a bit over-complicated. Code is more verbose (at least for continuous intervals) then it could be, and requires overloads/casts and/or parameterization for long, float, Integer etc

if (num < 1)
System.Out.Println("invalid case: " + num); // you should verify that anyway
else if (num <= 5)
System.Out.Println("1 to 5");
else if (num <= 10)
System.Out.Println("6 to 10");
else if (num <= 42)
System.Out.Println("11 to 42");
else
System.Out.Println("43 to +infinity");
  case 1: case 2: case 3: case 4: case 5:
System.out.println("testing case 1 to 5");
break;
case 6: case 7: case 8: case 9: case 10:
System.out.println("testing case 6 to 10");
break;
default:
System.out.println("default");

Try this if you must use switch.

public static int range(int num){
if ( 10 < num && num < 20)
return 1;
if ( 20 <= num && num < 30)
return 2;
return 3;
}


public static final int TEN_TWENTY = 1;
public static final int TWENTY_THIRTY = 2;


public static void main(String[]args){
int a = 110;
switch (range(a)){
case TEN_TWENTY:
System.out.println("10-20");
break;
case TWENTY_THIRTY:
System.out.println("20-30");
break;
default: break;
}
}

Here is a beautiful and minimalist way to go

(num > 1 && num < 5) ? first_case_method()
: System.out.println("testing case 1 to 5")
: (num > 5 && num < 7)  ? System.out.println("testing case 5 to 7")
: (num > 7 && num < 8)  ? System.out.println("testing case 7 to 8")
: (num > 8 && num < 9)  ? System.out.println("testing case 8 to 9")
: ...
: System.out.println("default");

Or you could use your solo cases as intended and use your default case to specify range instructions as :

switch(n) {
case 1 : System.out.println("case 1"); break;
case 4 : System.out.println("case 4"); break;
case 99 : System.out.println("case 99"); break;
default :
if (n >= 10 && n <= 15)
System.out.println("10-15 range");
else if (n >= 100 && n <= 200)
System.out.println("100-200 range");
else
System.out.println("Your default case");
break;
}

Use a NavigableMap implementation, like TreeMap.

/* Setup */
NavigableMap<Integer, Optional<String>> messages = new TreeMap<>();
messages.put(Integer.MIN_VALUE, Optional.empty());
messages.put(1, Optional.of("testing case 1 to 5"));
messages.put(6, Optional.of("testing case 6 to 10"));
messages.put(11, Optional.empty());


/* Use */
messages.floorEntry(3).getValue().ifPresent(System.out::println);

I know this post is old but I believe this answer deserves some recognition. There is no need to avoid the switch statement. This can be done in java but through the switch statement, not the cases. It involves using ternary operators.

public class Solution {


public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = Integer.parseInt(sc.nextLine());


switch ((1 <= num && num <= 5 ) ? 0 :
(6 <= num && num <= 10) ? 1 : 2) {


case 0:
System.out.println("I'm between one and five inclusive.");
break;
case 1:
System.out.println("I'm between 6 and 10 inclusive.");
break;
case 2:
System.out.println("I'm not between one and five or 6 and 10 inclusive.");
break;
}
}
}

For input number in range 0..100

int n1 = 75; // input value
String res; int n=0;
int[] a ={0,20,35,55,70,85,101};


for(; n1>=a[n]; n++);
switch(6-n+1) {
case 1: res="A"; break;
case 2: res="B"; break;
case 3: res="C"; break;
case 4: res="D"; break;
case 5: res="E"; break;
default:res="F";
}
System.out.println(res);

This type of behavior is not supported in Java. However, if you have a large project that needs this, consider blending in Groovy code in your project. Groovy code is compiled into byte code and can be run with JVM. The company I work for uses Groovy to write service classes and Java to write everything else.

It is supported as of Java 12. Check out JEP 354. No "range" possibilities here, but can be useful either.

switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);//number of letters
case TUESDAY                -> System.out.println(7);
case THURSDAY, SATURDAY     -> System.out.println(8);
case WEDNESDAY              -> System.out.println(9);
}

You should be able to implement that on ints too. Note through that your switch statement have to be exhaustive (using default keyword, or using all possible values in case statements).

after reading all the comments I didn't see anybody mention enhanced switch in which you can have multiple values in one case like this ->

switch(value){
case 1,2,3,4:
//dosth
break;
case 7,9,10,23:
//dosth
break;
}

and since in your case, there is only one expression in every case, you can do the following without the need to break every case->

switch (value) {
case 1, 2, 3, 4 -> System.out.println("one of 1,2,3,4 matched");
case 7, 9, 10, 23 -> System.out.println("one of 7,9,10,23 matched");
}

this is one of the many added benefits with enhanced switches in java.

Excellent contributions. In case it may be still helpful, I found an option to analyze whether inside a string there are characters different from letters and spaces:

string name = scEntry.nextLine();
int len = name.length();
int s = 0;
do {
int asc = name.codePointAt(s);
switch ((asc == 32) ? 0 : (64 < asc && asc < 91) ? 1 :
(96 < asc && asc < 123) ? 2 : 99) {
case 0, 1, 2 -> {
s++;
break;
}
case 99 -> {
s = 0;
System.out.println("Type in only letters [A-Za-z]
or spaces");
System.out.print("Type the user name again: ");
name = scEntry.nextLine();
len = name.length();
break;
}
} while (s < len);
s = 0;

In this example, the letters' ASCII codes along with the "space" ASCII code are grouped and represented by the numbers 0, 1 or 2. ASCII codes different from the above mentioned, are grouped in the value "99", so I can inform any thing about them to the user.

Apart from switch statements, since Java 14 SE there are switch expressions you can use as an alternative when each case produces some result. If handling a non-integer Math.round() can be used, for example.

String result = switch (Math.round(value)) {
case 1, 2, 3, 4, 5:
// handle case 1
yield "result of case 1";
case 6, 7, 8, 9, 10:
// handle case 2
yield "result of case 2";
default:
// handle the default case
yield "result of the default case";
}


System.out.println("result = " + result);

The difference from the switch statement is that all cases must be covered (often with the default case).