जावा स्विच स्टेटमेंट कई मामले


118

बस एक जावा स्विच स्टेटमेंट के लिए कई मामलों का उपयोग करने का पता लगाने की कोशिश कर रहा है। यहाँ एक उदाहरण है जो मैं करने की कोशिश कर रहा हूँ:

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

बनाम करने के लिए:

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

किसी भी विचार अगर यह संभव है, या एक अच्छा विकल्प क्या है?


12
ऐसा लगता है कि आप पूर्णांक का उपयोग कर रहे हैं, इसलिए यदि आप जानते हैं कि आपकी सीमाएं निश्चित आकार की हैं, तो आप हमेशा स्विच (चर / FIXED_SIZE_OF_RANGE) {केस 0: ... डिफ़ॉल्ट: ब्रेक कर सकते हैं; }
पॉलुकेरग्लर

जवाबों:


80

अफसोस की बात है, यह जावा में संभव नहीं है। आपको if-elseस्टेटमेंट्स का उपयोग करना होगा ।


1
@FunJavaCode AFAIK आप vb.net में ऐसा कर सकते हैं। यहाँ एक उदाहरण है
बाला आर

1
@YuryLitvinov क्या आप विस्तार करना चाहते हैं कि आपको क्यों लगता है कि यह गलत है?
बाला आर

1
मेरा उत्तर यह साबित करता है कि यह गलत है, यह OO है और इस सटीक समस्या से निपटने के लिए एक ज्ञात और स्वीकृत पैटर्न है if/elseif/else, जिसमें भाषा की परवाह किए बिना कई नेस्टेड बयानों की आवश्यकता होती है ।

1
इन लिंक का उपयोग करके SWITCH मामले में OR स्थिति प्राप्त करना संभव है ... plz इसे देखें: - stackoverflow.com/a/16706729/3946958
रवींद्र कुशवाहा

4
भाई इसका संभावित उपयोग बिना ब्रेक का उपयोग किए कई मामले लिख सकता है और मामले के अंत में आप अपना तर्क लिख सकते हैं जैसे: केस some_value: case some_value: case some_value: you_logic_goes_here break;
अनूपब्रीयन २

85

दूसरा विकल्प पूरी तरह से ठीक है। मुझे यकीन नहीं है कि एक उत्तरदाता ने कहा कि यह संभव नहीं था। यह ठीक है, और मैं हर समय ऐसा करता हूं:

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

50
प्रश्नकर्ता ने कहा कि यह "बनाम" कर। वह समझता है कि आपने जो सूचीबद्ध किया है, वह मान्य है, वह पहली बात उस का INSTEAD करने की कोशिश कर रहा था।
ब्लेन मैक्लो

45
मुझे खेद है, लेकिन मैं यह नहीं देखता कि 95 मामलों को एक पंक्ति में कैसे सूचीबद्ध किया जाए जो एक ही चीज पर जाएं किसी भी चीज का समाधान है। अगर मुझे लगा कि किसी भी कोड में मैं उन्हें नीचे ट्रैक करूंगा, उनका अपहरण करूंगा, उन्हें व्यक्तिगत रूप से GLDDOS तक पहुंचाऊंगा, और आशा है कि वह उन्हें उन परीक्षणों का सबसे घातक अनुक्रम प्रदान करेगी जो वह पा सकते हैं।
animuson

1
@ मानसून के ऊपर, वह 60 बार उठ जाता है .... जाओ आंकड़ा। मैं यहाँ आया था coz मैं ऐसा नहीं करना चाहता था जो वह सही जवाब देना चाहता है
किलोजॉय

डाउनवोटिंग के रूप में इस सवाल का जवाब नहीं है। । .चाहिए, जाहिर तौर पर, इस उत्तर को लिखने के लिए प्रश्न पढ़ा भी नहीं गया था।
इहानी

50
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

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


4
यह उसके प्रश्न के "बनाम" भाग के समान है, जिसे वह टालना चाहता था।
Bdoserror

2
कोड केवल उत्तर लगभग उतने ही बुरे हैं जितने लिंक केवल उत्तर। वे वास्तव में बिल्कुल जवाब नहीं दे रहे हैं। एक अच्छे उत्तर में स्पष्टीकरण और तर्क शामिल हैं और संभवतः कुछ स्रोत या प्राधिकरण हैं।
मार्कस

3
यह कुछ भी नहीं से बेहतर है, कुछ लोगों को लगता है कि सबसे अच्छा जवाब के रूप में, सरल और प्रत्यक्ष
D4rWiNS

48

हो सकता है कि कुछ पिछले उत्तरों की तरह सुरुचिपूर्ण न हों, लेकिन यदि आप कुछ बड़ी श्रेणियों के साथ स्विच मामलों को प्राप्त करना चाहते हैं, तो बस एक ही मामले में पहले से सीमाएं जोड़ दें:

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

11
मैं इसकी सिफारिश नहीं करूंगा। यदि आप केवल कोड के माध्यम से चलते हैं, तो आपके पास अंतर्ज्ञान होगा जिसका case 1अर्थ है variable == 1, जिससे भ्रम होता है और लंबे समय में बहुत दर्द होता है। यदि आपको इसे पठनीय बनाने के लिए अपने कोड में टिप्पणियां डालने की आवश्यकता है, तो आपने कुछ गलत किया IMHO।
क्रैकोर

21

एक ऑब्जेक्ट ओरिएंटेड विकल्प को अत्यधिक बड़े switchऔर if/elseनिर्माणों को बदलने के Chain of Responsibility Patternलिए निर्णय लेने के लिए मॉडल का उपयोग करना है।

जिम्मेदारी पैटर्न की श्रृंखला

जिम्मेदारी पैटर्न की श्रृंखला एक अनुरोध के स्रोत को अलग करने की अनुमति देती है, जो यह तय करती है कि अनुरोध के लिए संभावित बड़ी संख्या में हैंडलर को क्या कार्रवाई करनी चाहिए। श्रृंखला की भूमिका का प्रतिनिधित्व करने वाला वर्ग हैंडलर की सूची के स्रोत से अनुरोधों को तब तक प्रसारित करता है जब तक कि कोई हैंडलर अनुरोध को स्वीकार नहीं करता है और इसे कार्रवाई करता है।

यहां एक उदाहरण कार्यान्वयन है जो कि जेनरिक का उपयोग करके टाइप सेफ भी है।

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

    }
}

यह सिर्फ एक त्वरित पुआल आदमी है जिसे मैंने कुछ मिनटों में मार दिया था, एक अधिक परिष्कृत कार्यान्वयन कुछ प्रकार के कार्यान्वयन के लिए अनुमति दे सकता है इसे कॉल बैक आईओसी शैली के अधिक बनाने के लिए कार्यान्वयन के उदाहरणों Command Patternमें इंजेक्ट किया जा सकता Caseहै।

एक बार इस दृष्टिकोण के बारे में अच्छी बात यह है कि स्विच / केस स्टेटमेंट्स सभी साइड इफेक्ट्स के बारे में हैं, यह क्लासेस में साइड इफेक्ट्स को इनकैप्सुलेट करता है ताकि उन्हें प्रबंधित किया जा सके, और इसे बेहतर तरीके से इस्तेमाल किया जा सके, यह एक कार्यात्मक भाषा में पैटर्न मैचिंग की तरह अधिक समाप्त होता है यह कोई बुरी बात नहीं है।

मैं इस Gist को Github पर कोई भी अपडेट या एन्हांसमेंट पोस्ट करूंगा ।


2
यदि आपके पास बड़ी मात्रा में चर हैं, तो मैं सहमत हूं, केस स्टेटमेंट और बड़ा है। यदि आप बहुत सारे केस स्टेटमेंट कर रहे हैं तो आप ओओ सिद्धांतों का उपयोग नहीं कर रहे हैं और साथ ही साथ आप कर सकते हैं।
ब्लेन मैक्लो

11

इस सवाल के अनुसार , यह पूरी तरह से संभव है।

बस उन सभी मामलों को शामिल करें जिनमें समान तर्क एक साथ हों, और 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एक और पर चला जाएगा caseजब तक breakया return

संपादित करें:

टिप्पणी का जवाब देना, अगर हमारे पास वास्तव में एक ही तर्क के साथ 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है, पसंद है।


2
प्रश्न पहले से ही इसे एक समाधान के रूप में प्रस्तुत करता है और पूछता है कि क्या सीमा के हर मूल्य को कोड किए बिना एक सीमा निर्दिष्ट करने का एक तरीका है (ओपी को 96 caseबयानों की आवश्यकता होगी !)। मुझे डर है कि मैं स्वीकृत जवाब से सहमत हूं।
बोहेमियन

टिप्पणी के लिए धन्यवाद। संपादित देखें, हो सकता है। मैं मानता हूं कि यह सब परिदृश्य पर निर्भर करता है, और 5 बनाम 95 मामला नहीं हो सकता है।
पश्चिमीगंज

6

मूल रूप से:

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

यदि आपको वास्तव में एक स्विच का उपयोग करने की आवश्यकता है, तो ऐसा इसलिए होगा क्योंकि आपको कुछ श्रेणियों के लिए विभिन्न चीजें करने की आवश्यकता होती है। उस स्थिति में, हां, आप गन्दा कोड रखने जा रहे हैं, क्योंकि चीजें जटिल हो रही हैं और केवल ऐसी चीजें हैं जो पैटर्न का पालन करती हैं, अच्छी तरह से संपीड़ित करने जा रही हैं।

स्विच का एकमात्र कारण वैरिएबल नाम टाइप करने पर बचाना है यदि आप केवल संख्यात्मक स्विचिंग मानों का परीक्षण कर रहे हैं। आप 100 चीजों पर स्विच करने नहीं जा रहे हैं, और वे सभी एक ही काम करने वाले नहीं हैं। यह एक 'अगर' चंक की तरह लगता है।


4

// गैर-योग्य कोड उदाहरण

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

वास्तविक जवाब जो अंगूठे के लायक था। अच्छा लगा।
user1735921

3

पिछले जावा -12 रिलीज से एक ही मामले में कई स्थिरांक लेबल पूर्वावलोकन भाषा सुविधा में उपलब्ध है

यह वास्तविक दुनिया के उपयोग के आधार पर डेवलपर की प्रतिक्रिया को भड़काने के लिए JDK फीचर रिलीज़ में उपलब्ध है; यह भविष्य के जावा एसई प्लेटफॉर्म में स्थायी हो सकता है।

ऐसा लग रहा है:

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

और देखें JEP 325: स्विच एक्सप्रेशंस (पूर्वावलोकन)


2

वावर लाइब्रेरी का उपयोग करके इसे संभालना संभव है

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

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

यह निश्चित रूप से केवल मामूली सुधार है क्योंकि सभी मामलों को अभी भी स्पष्ट रूप से सूचीबद्ध करने की आवश्यकता है। लेकिन कस्टम विधेय को परिभाषित करना आसान है:

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

मैच एक अभिव्यक्ति है इसलिए यहां यह Runnableसीधे तौर पर इनवॉइस करने के तरीकों की बजाय उदाहरण की तरह देता है । मैच के प्रदर्शन के बाद Runnableनिष्पादित किया जा सकता है।

अधिक जानकारी के लिए कृपया आधिकारिक दस्तावेज देखें ।


1

विकल्प के लिए आप नीचे के रूप में उपयोग कर सकते हैं:

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

    }

या निम्न कोड भी काम करता है

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

1

JEP 354: JDK-13 और JEP 361 में स्विच एक्सप्रेशंस (प्रीव्यू) : JDK-14 में स्विच एक्सप्रेशंस (स्टैंडर्ड) स्विच स्टेटमेंट का विस्तार करेगा,इसलिए इसे अभिव्यक्ति के रूप में इस्तेमाल किया जा सकता है

अब आप कर सकते हैं:

  • स्विच अभिव्यक्ति से सीधे चर असाइन करें ,
  • स्विच लेबल के नए रूप का उपयोग करें ( case L ->):

    "केस एल ->" स्विच लेबल के दाईं ओर कोड एक अभिव्यक्ति, एक ब्लॉक, या (सुविधा के लिए) एक फेंक स्टेटमेंट होना प्रतिबंधित है।

  • प्रति मामले में कई स्थिरांक का उपयोग करें, जो अल्पविराम द्वारा अलग किए जाते हैं,
  • और इसके अलावा अधिक मूल्य विराम नहीं हैं :

    एक स्विच अभिव्यक्ति से एक मूल्य प्राप्त करने के लिए, breakमूल्य कथन के साथ एक yieldबयान के पक्ष में गिरा दिया जाता है ।

स्विच अभिव्यक्ति उदाहरण:

public class SwitchExpression {

  public static void main(String[] args) {
      int month = 9;
      int year = 2018;
      int numDays = switch (month) {
        case 1, 3, 5, 7, 8, 10, 12 -> 31;
        case 4, 6, 9, 11 -> 30;
        case 2 -> {
          if (java.time.Year.of(year).isLeap()) {
            System.out.println("Wow! It's leap year!");
            yield 29;
          } else {
            yield 28;
          }
        }
        default -> {
          System.out.println("Invalid month.");
          yield 0;
        }
      };
      System.out.println("Number of Days = " + numDays);
  }
}

0

हार्ड-कोडित मूल्यों का उपयोग करने के बजाय एक विकल्प स्विच स्टेटमेंट पर रेंज मैपिंग का उपयोग कर सकता है:

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;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.