programing

Java switch 문 여러 경우

nasanasas 2020. 8. 14. 07:52
반응형

Java switch 문 여러 경우


Java switch 문에 여러 사례를 사용하는 방법을 알아 내려고합니다. 다음은 내가하려는 작업의 예입니다.

switch (variable)
{
    case 5..100:
        doSomething();
    break;
}

해야 할 일과 비교 :

switch (variable)
{
    case 5:
    case 6:
    etc.
    case 100:
        doSomething();
    break;
}

이것이 가능하다면 어떤 아이디어 나 좋은 대안은 무엇입니까?


슬프게도 Java에서는 불가능합니다. if-else사용에 의지해야 합니다.


두 번째 옵션은 완전히 괜찮습니다. 응답자가 왜 불가능하다고 말했는지 모르겠습니다. 이것은 괜찮습니다. 저는 항상 이것을합니다.

switch (variable)
{
    case 5:
    case 6:
    etc.
    case 100:
        doSomething();
    break;
}

이전 답변만큼 우아하지는 않지만 큰 범위가 거의없는 스위치 케이스를 얻으려면 미리 범위를 단일 케이스로 결합하십시오.

// make a switch variable so as not to change the original value
int switchVariable = variable;

//combine range 1-100 to one single case in switch
if(1 <= variable && variable <=100)
    switchVariable = 1;
switch (switchVariable) 
{ 
    case 0:
        break; 
    case 1:
        // range 1-100
        doSomething(); 
        break;
    case 101: 
        doSomethingElse(); 
        break;
    etc.
} 

public class SwitchTest {
    public static void main(String[] args){
        for(int i = 0;i<10;i++){
            switch(i){
                case 1: case 2: case 3: case 4: //First case
                    System.out.println("First case");
                    break;
                case 8: case 9: //Second case
                    System.out.println("Second case");
                    break;
                default: //Default case
                    System.out.println("Default case");
                    break;
            }
        }
    }
}

밖:

Default case
First case
First case
First case
First case
Default case
Default case
Default case
Second case
Second case

서버 : http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html


옵션을 지향 한 개체 과도하게 큰 교체 switchif/else구조는을 사용하는 Chain of Responsibility Pattern의사 결정을 모델링 할 수 있습니다.

책임의 사슬 패턴

책임 체인 패턴을 사용하면 요청에 대해 잠재적으로 많은 수의 핸들러 중 어느 것이 조치를 취해야하는지 결정하는 것으로부터 요청 소스를 분리 할 수 ​​있습니다. 체인 역할을 나타내는 클래스는 핸들러가 요청을 수락하고 조치를 취할 때까지 핸들러 목록을 따라 소스의 요청을 채널링합니다.

다음은 Generics를 사용하는 Type Safe 인 구현의 예입니다.

import java.util.ArrayList;
import java.util.List;

/**
* Generic enabled Object Oriented Switch/Case construct
* @param <T> type to switch on
*/
public class Switch<T extends Comparable<T>>
{
    private final List<Case<T>> cases;

    public Switch()
    {
        this.cases = new ArrayList<Case<T>>();
    }

    /**
     * Register the Cases with the Switch
     * @param c case to register
     */
    public void register(final Case<T> c) { this.cases.add(c); }

    /**
     * Run the switch logic on some input
     * @param type input to Switch on
     */
    public void evaluate(final T type)
    {
        for (final Case<T> c : this.cases)
        {
            if (c.of(type)) { break; }
        }
    }

    /**
     * Generic Case condition
     * @param <T> type to accept
     */
    public static interface Case<T extends Comparable<T>>
    {
        public boolean of(final T type);
    }

    public static abstract class AbstractCase<T extends Comparable<T>> implements Case<T>
    {
        protected final boolean breakOnCompletion;

        protected AbstractCase()
        {
            this(true);
        }

        protected AbstractCase(final boolean breakOnCompletion)
        {
            this.breakOnCompletion = breakOnCompletion;
        }
    }

    /**
     * Example of standard "equals" case condition
     * @param <T> type to accept
     */
    public static abstract class EqualsCase<T extends Comparable<T>> extends AbstractCase<T>
    {
        private final T type;

        public EqualsCase(final T type)
        {
            super();
            this.type = type;
        }

        public EqualsCase(final T type, final boolean breakOnCompletion)
        {
            super(breakOnCompletion);
            this.type = type;
        }
    }

    /**
     * Concrete example of an advanced Case conditional to match a Range of values
     * @param <T> type of input
     */
    public static abstract class InRangeCase<T extends Comparable<T>> extends AbstractCase<T>
    {
        private final static int GREATER_THAN = 1;
        private final static int EQUALS = 0;
        private final static int LESS_THAN = -1;
        protected final T start;
        protected final T end;

        public InRangeCase(final T start, final T end)
        {
            this.start = start;
            this.end = end;
        }

        public InRangeCase(final T start, final T end, final boolean breakOnCompletion)
        {
            super(breakOnCompletion);
            this.start = start;
            this.end = end;
        }

        private boolean inRange(final T type)
        {
            return (type.compareTo(this.start) == EQUALS || type.compareTo(this.start) == GREATER_THAN) &&
                    (type.compareTo(this.end) == EQUALS || type.compareTo(this.end) == LESS_THAN);
        }
    }

    /**
     * Show how to apply a Chain of Responsibility Pattern to implement a Switch/Case construct
     *
     * @param args command line arguments aren't used in this example
     */
    public static void main(final String[] args)
    {
        final Switch<Integer> integerSwitch = new Switch<Integer>();
        final Case<Integer> case1 = new EqualsCase<Integer>(1)
        {
            @Override
            public boolean of(final Integer type)
            {
                if (super.type.equals(type))
                {
                    System.out.format("Case %d, break = %s\n", type, super.breakOnCompletion);
                    return super.breakOnCompletion;
                }
                else
                {
                    return false;
                }
            }
        };
        integerSwitch.register(case1);
        // more instances for each matching pattern, granted this will get verbose with lots of options but is just
        // and example of how to do standard "switch/case" logic with this pattern.
        integerSwitch.evaluate(0);
        integerSwitch.evaluate(1);
        integerSwitch.evaluate(2);


        final Switch<Integer> inRangeCaseSwitch = new Switch<Integer>();
        final Case<Integer> rangeCase = new InRangeCase<Integer>(5, 100)
        {
            @Override
            public boolean of(final Integer type)
            {
                if (super.inRange(type))
                {
                    System.out.format("Case %s is between %s and %s, break = %s\n", type, this.start, this.end, super.breakOnCompletion);
                    return super.breakOnCompletion;
                }
                else
                {
                    return false;
                }
            }
        };
        inRangeCaseSwitch.register(rangeCase);
        // run some examples
        inRangeCaseSwitch.evaluate(0);
        inRangeCaseSwitch.evaluate(10);
        inRangeCaseSwitch.evaluate(200);

        // combining both types of Case implementations
        integerSwitch.register(rangeCase);
        integerSwitch.evaluate(1);
        integerSwitch.evaluate(10);

    }
}

이것은 내가 몇 분 만에 채찍질 한 빠른 짚 맨일 뿐이다. 좀 더 정교한 구현은 콜백 IoC 스타일로 만들기 위해 구현 인스턴스 에 어떤 종류의 Command Pattern주입을 허용 할 수 있다 Case.

이 접근 방식에 대한 좋은 점은 Switch / Case 문이 모두 부수적 영향에 관한 것이라는 점입니다. 이것은 부수 효과를 클래스에 캡슐화하여 관리하고 더 잘 재사용 할 수 있도록합니다. 결국 기능적 언어의 패턴 일치와 비슷해집니다. 그것은 나쁜 것이 아닙니다.

Gist대한 업데이트 나 개선 사항을 Github에 게시하겠습니다 .


원래:

if (variable >= 5 && variable <= 100)
{
    doSomething();
}

정말 스위치를 사용해야한다면 특정 범위에 대해 다양한 작업을해야하기 때문일 것입니다. 이 경우, 예, 당신은 복잡한 코드를 갖게 될 것입니다. 왜냐하면 상황이 복잡해지고 패턴을 따르는 것만 잘 압축 될 것이기 때문입니다.

전환의 유일한 이유는 숫자 전환 값을 테스트하는 경우 변수 이름 입력을 절약하기위한 것입니다. 당신은 100 가지를 켜지 않을 것이고, 그들은 모두 같은 일을하지 않을 것입니다. 그것은 'if'청크처럼 들립니다.


이 질문 에 따르면 전적으로 가능합니다.

동일한 논리를 포함하는 모든 케이스를 함께 배치하고 break뒤에 배치하지 마십시오 .

switch (var) {
    case (value1):
    case (value2):
    case (value3):
        //the same logic that applies to value1, value2 and value3
        break;
    case (value4):
        //another logic
        break;
}

case없이는 또는 까지 break다른 것으로 점프하기 때문 입니다.casebreakreturn

편집하다:

댓글에 답장하면 논리가 동일한 95 개의 값이 있지만 논리가 다른 케이스 수가 훨씬 적다면 다음과 같이 할 수 있습니다.

switch (var) {
     case (96):
     case (97):
     case (98):
     case (99):
     case (100):
         //your logic, opposite to what you put in default.
         break;
     default: 
         //your logic for 1 to 95. we enter default if nothing above is met. 
         break;
}

더 세밀한 제어가 필요한 경우 if-else선택합니다.


// 비준수 코드 예제

switch (i) {
  case 1:
    doFirstThing();
    doSomething();
    break;
  case 2:
    doSomethingDifferent();
    break;
  case 3:  // Noncompliant; duplicates case 1's implementation
    doFirstThing();
    doSomething();
    break;
  default:
    doTheRest();
}

if (a >= 0 && a < 10) {
  doFirstThing();

  doTheThing();
}
else if (a >= 10 && a < 20) {
  doTheOtherThing();
}
else if (a >= 20 && a < 50) {
  doFirstThing();
  doTheThing();  // Noncompliant; duplicates first condition
}
else {
  doTheRest();
}

// 준수 솔루션

switch (i) {
  case 1:
  case 3:
    doFirstThing();
    doSomething();
    break;
  case 2:
    doSomethingDifferent();
    break;
  default:
    doTheRest();
}

if ((a >= 0 && a < 10) || (a >= 20 && a < 50)) {
  doFirstThing();
  doTheThing();
}
else if (a >= 10 && a < 20) {
  doTheOtherThing();
}
else {
  doTheRest();
}

It is possible to handle this using Vavr library

import static io.vavr.API.*;
import static io.vavr.Predicates.*;

Match(variable).of(
    Case($(isIn(5, 6, ... , 100)), () -> doSomething()),
    Case($(), () -> handleCatchAllCase())
);

This is of course only slight improvement since all cases still need to be listed explicitly. But it is easy to define custom predicate:

public static <T extends Comparable<T>> Predicate<T> isInRange(T lower, T upper) {
    return x -> x.compareTo(lower) >= 0 && x.compareTo(upper) <= 0;
}

Match(variable).of(
    Case($(isInRange(5, 100)), () -> doSomething()),
    Case($(), () -> handleCatchAllCase())
);

Match is an expression so here it returns something like Runnable instance instead of invoking methods directly. After match is performed Runnable can be executed.

For further details please see official documentation.


for alternative you can use as below:

if (variable >= 5 && variable <= 100) {
        doSomething();

    }

or the following code also works

switch (variable)
{
    case 5:
    case 6:
    etc.
    case 100:
        doSomething();
    break;
}

From the last java-12 release multiple constants in the same case label is available in preview language feature

It is available in a JDK feature release to provoke developer feedback based on real world use; this may lead to it becoming permanent in a future Java SE Platform.

It looks like:

switch(variable) {
    case 1 -> doSomething();
    case 2, 3, 4 -> doSomethingElse();
};

See more JEP 325: Switch Expressions (Preview)


One alternative instead of using hard-coded values could be using range mappings on the the switch statement instead:

private static final int RANGE_5_100 = 1;
private static final int RANGE_101_1000 = 2;
private static final int RANGE_1001_10000 = 3;

public boolean handleRanges(int n) {
    int rangeCode = getRangeCode(n);
    switch (rangeCode) {
        case RANGE_5_100: // doSomething();
        case RANGE_101_1000: // doSomething();
        case RANGE_1001_10000: // doSomething();
        default: // invalid range
    }
}

private int getRangeCode(int n) {
    if (n >= 5 && n <= 100) {
        return RANGE_5_100;
    } else if (n >= 101 && n <= 1000) {
        return RANGE_101_1000;
    } else if (n >= 1001 && n <= 10000) {
        return RANGE_1001_10000;
    }

    return -1;
}

참고URL : https://stackoverflow.com/questions/5086322/java-switch-statement-multiple-cases

반응형