각 경우에 값 범위와 함께 switch 문을 사용합니까?


92

Java에서 각 케이스에 둘 이상의 값이 포함 된 스위치 문을 작성할 수 있습니까? 예를 들어 (분명히 다음 코드는 작동하지 않습니다) :

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에도 비슷한 것이 있습니까? 아니면 대신 if, else if문을 사용해야 합니까?


이것을 허용하는 일반 C의 확장도 있습니다.
— arshajii 2013 년

이 경우 if/else더 나은 해결책이 될 수 있습니다.
— Eric Wang

답변:


98

Java에는 그런 종류의 것이 없습니다. 다음을 수행하지 않는 이유는 무엇입니까?

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

1
이것은 훌륭하게 작동하고 간단합니다. 당신이 번호를 선택하려는 경우에도하지 당신이 필요로하는 모든 범위에있는 경우 (isBetween ..., 좋은 일!.
— a54studio

1
@missingfaktor 나는 당신의 대답을 약간 비판했습니다 . 그래서, 당신은 아마도 무언가에 답하고 싶을 것입니다. 그래도 +1.
— Alexander Malakhov

@MCEmperor, 개인 서식 기본 설정으로 내 대답을 편집하지 마십시오. 그것은 유용한 편집이 아닙니다.
— missingfaktor

@missingfaktor 죄송합니다. 그러나 그 편집은 오래 전에 승인되었습니다. 내가 그런 일을 한 적이 있다는 것도 기억하지 못했습니다.
— MC Emperor

76

switch명령문을 사용 하여 이러한 종류의 동작에 가장 가까운 것은

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

사용 if진술.


29

다른 대안은 다음과 같이 나누어 수학 연산을 사용하는 것입니다.

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

그러나 보시다시피 범위가 각 경우에 고정 된 경우에만 사용할 수 있습니다.


6
이것은 100으로 나눈 HTTP 상태 코드와 잘 작동
— 스테판

13

Java에서는 그렇게 할 수 없다고 생각합니다. 가장 좋은 방법은 범위의 마지막 경우에 코드를 넣는 것입니다.

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:
     //
}

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

9

나는이 게시물이 오래되었다는 것을 알고 있지만이 답변은 인정받을 가치가 있다고 생각합니다. switch 문을 피할 필요가 없습니다. 이것은 Java에서 수행 할 수 있지만 case가 아닌 switch 문을 통해 수행 할 수 있습니다. 삼항 연산자를 사용합니다.

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

1
좋은 해결책! 자바 7 당신의 경우는 더 예를 들어 자기 문서화, 그래서 높은 당신은 또한 문자열에 전환 할 수있는 switch ((1 <= num && num <= 5 ) ? "1 .. 5" : ...다음과 case "1 .. 5":.
— Daniel Widdis

@DanielWiddis : 일관성을 보장하기 위해 문자열 대신 열거 형을 사용하는 것이 좋습니다.
— nmatt

@nmatt 일반적으로 동의합니다. 나는 "1 .. 5"스타일 구문의 사용을 허용하려고했다.
— Daniel Widdis

2
@DanielWiddis : 확실히 좋은 일입니다. 열거 형 상수의 이름을 FROM_1_TO_5와 같이 지정하겠습니다. 일반적으로 범위에는 특정 의미가 있으며이 경우 범위의 의미에 따라 열거 형 상수의 이름을 지정할 수 있습니다.
— nmatt

1
두 옵션 중 하나가 0, 1 또는 2보다 낫다는 데 동의 할 수 있다고 생각합니다.
— Daniel Widdis

6

또는 의도 한대로 솔로 케이스를 사용하고 기본 케이스를 사용하여 범위 지침을 다음과 같이 지정할 수 있습니다.

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

이것은 내가 항상하는 일이지만, 예를 들어 다음과 같이 경우 사이에 주석을 추가합니다. // 10-15 기본값 아래 참조
— Perdi Estaquel

5

스위치를 사용해야하는 경우 이것을 시도하십시오.

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

당신도 설명해 주시겠습니까 ..?
— user1140237

함수 범위는 입력 인수에 따라 일부 값을 반환하므로 여기서 "값 범위"감지를 스위치 케이스 절과 함께 수행 할 수 있습니다.
— zl9394

이것은 내 유스 케이스에서 작동합니다. 2 개의 int 변수가 있고 2 개의 변수가 (10-20), (20-30), ....과 같은 동일한 범위에 있는지 확인하고 싶습니다. 이렇게
— Sameer Kazi

magic int 값 대신 enum을 사용하는 것이 좋습니다.
— nmatt

4

아니 당신은 할 수 없습니다. 당신이 할 수있는 최선은

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

3

switch 문에 의해 허용되는 fall throughcase 메커니즘을 사용하여 동일한 문 에서 여러 조건을 그룹화 할 수 있습니다. 이는 Java 자습서 에서 언급 되고 섹션 §14.11에 완전히 지정되어 있습니다 . 스위치 문 의 Java 언어 사양 .

다음 코드 스 니펫은 자습서의 예제에서 가져온 것으로, 매월 일 수를 계산합니다 (1 개월부터 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;
}

보시다시피 단일 case명령문 에서 값 범위를 다루는 유일한 대안은 가능한 값을 하나씩 하나씩 나열하는 것입니다. 추가 예로서 다음은 질문에서 의사 코드를 구현하는 방법입니다.

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

3

enum범위를 나타내는 데 사용할 수 있습니다.

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

3

Java 12부터 지원됩니다. 체크 아웃 . JEP 354를 . 여기서 "범위"가능성은 없지만 유용 할 수 있습니다.

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

int에서도 구현할 수 있어야합니다. switch 문은 완전해야합니다 ( default키워드 사용 또는 case 문에서 가능한 모든 값 사용).


3

아름답고 미니멀 한 방법이 있습니다.

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

이것을 설명 할 수 있습니까 ?? -나는 'mini ifs'를 얻지 만 그 idk가 아닙니다.
— Kamin Pallaghy

@Tunaki 이것은 if..elseif삼항 연산자 ( condition ? statementIfTrue : statementIfFalse) 를 캐스케이드로 사용 하는 대안 입니다.
— Williem

2

@missingfaktor의 대답은 실제로 정확하지만 약간 복잡합니다. 코드는 (적어도 연속 간격의 경우) 더 장황 할 수 있으며 long, float, Integer 등에 대한 오버로드 / 캐스트 및 / 또는 매개 변수화가 필요합니다.

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

3
응답이 늦어서 죄송합니다. 최근에 SO 응답을 따라갈 수 없습니다. 당신의 비판에 하나씩 답변 해 드리겠습니다. 1. 코드는 좀 더 장황합니다. 그렇습니다. 또한 중복 계산도 수행합니다. 그러나 그 IMO는이 경우 명확성을 돕습니다. 코드에서 사다리를 통과 할 때 이전 사례를 기억해야합니다.
— missingfaktor 2014-06-20

2
과부하 및 캐스트 요구에 관해서는 유효한 비판 IMO가 아닙니다. Java에는 숫자 유형을 추상화하는 현명한 방법이 없다는 것은이 접근 방식보다 Java의 한계에 대해 말합니다. Num이 점을 더 잘 이해하고 싶다면 Haskell의 유형 클래스 를 탐색 할 수 있습니다 .
— missingfaktor 2014-06-20

@missingfaktor 1. 그게 취향의 문제라고 생각합니다. 연속 간격을 다룰 때 개인적으로 ifs를 낮은 하위 범위에서 점차적으로 쏟아져 나오는 것처럼 생각하고 싶습니다 . 또한 중복 계산은 전혀 문제가되지 않지만 중복 비교는 약간 걱정 스럽습니다. 예를 들어 일부 편집 후 인접한 비교를 동기화하지 않는 것이 더 간단 해집니다 if (isBetween(x, 1, 4)) {...} else if (isBetween(x, 6, 10)). 어쨌든 큰 문제는 아닙니다.
— Alexander Malakhov 2014-06-23

2. 동의 함-Java의 제한 사항이지만 이것이 우리가 작업해야하는 것이며 원본 코드는 다양한 유형에 대해 복제됩니다. 이 특별한 경우에는 Number 클래스 를 사용하여 문제를 완화 할 수 있지만 Haskell의 접근 방식이 더 낫습니다 (진짜 Haskell을 배우지 못했지만 C ++의 "Concepts Light"와 비슷합니다. 또한 Real, 아니라고 생각합니다 Num).
— Alexander Malakhov 2014 년

2

NavigableMap와 같은 구현을 사용하십시오 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);

훌륭한 솔루션! if (messages.floorEntry(value)!=null) 정수 값을 사용하는 경우 null을 확인하는 것을 잊지 마십시오
— Ch Vas

1
@ChVas 여기서 맵이 설정된 방식은 floorEntry()반환되지 않습니다 null( Integer.MIN_VALUE키 삽입은 이를 방지하기위한 것입니다). 그러나 값 유형에 관계없이 유효한 범위를 벗어난 키를 처리하는 방법을 결정해야합니다.
— erickson

0

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

0

이러한 유형의 동작은 Java에서 지원되지 않습니다. 그러나이를 필요로하는 대규모 프로젝트가있는 경우 프로젝트에서 Groovy 코드를 혼합하는 것을 고려하십시오. Groovy 코드는 바이트 코드로 컴파일되며 JVM과 함께 실행할 수 있습니다. 내가 일하는 회사는 Groovy를 사용하여 서비스 클래스를 작성하고 Java를 사용하여 다른 모든 것을 작성합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.