ChatGPT解决这个技术问题 Extra ChatGPT

在每种情况下都使用具有一系列值的 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 语句?

甚至在普通 C 语言中也有允许这样做的扩展。
在这种情况下,也许 if/else 是一个更好的解决方案。
不是今天,但是 Java 人员正在探索这方面的选项以及 switch 表达式中的模式匹配(我会说从 Scala 中大量借用)。在本文档中搜索“守卫”,其中包含可能的想法:cr.openjdk.java.net/~briangoetz/amber/switch-rehab.html

m
missingfaktor

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

这很好用而且很简单。此外,如果您想选择不在范围内的数字,您只需要 if(!isBetween... ,干得好。
@missingfaktor 我已经criticized回答了您的一些问题。所以,你可能想回复一些东西。 +1虽然。
@MCEmperor,请不要使用您的个人格式偏好编辑我的答案。这不是一个有用的编辑。
@missingfaktor 对不起。但是那个编辑很久以前就被批准了。我什至不记得我曾经这样做过。
奇怪的是,switch 语句在我遇到的大多数语言中似乎几乎没有用,不知道为什么它们不进一步开发它们。奇怪的是,即使是像范围这样简单的东西也是不可能的。
J
Jeffrey

使用 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 语句。


我几乎可以肯定这正是他试图避免的。
@Hasen 这就是为什么我建议使用 if 语句来代替:)
那么像上面的 Eric Wang 那样发表评论会更好。
H
Hayi Nukman

另一种选择是通过除法来使用数学运算,例如:

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

但是,正如您所看到的,这只能在每种情况下固定范围时使用。


这适用于 http 状态代码除以 100。
佚名

我认为你不能在 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:
     //
}

D
DarkHark

我知道这篇文章很旧,但我相信这个答案值得一些认可。没有必要避免 switch 语句。这可以在 java 中完成,但通过 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;
        }
    }
}

不错的解决方案!在 Java 7 和更高版本中,您还可以打开字符串,这样您的案例就更加自我记录,例如,switch ((1 <= num && num <= 5 ) ? "1 .. 5" : ... 然后是 case "1 .. 5":
@DanielWiddis:我建议使用枚举而不是字符串,以确保一致性。
@nmatt 一般同意。我试图允许使用“1 .. 5”样式语法。
@DanielWiddis:当然是好事;我会将枚举常量命名为 FROM_1_TO_5。通常范围有一定的含义,在这种情况下,枚举常量可以根据范围的含义来命名。
我认为我们可以同意任何一个选项都比 0、1 或 2 更好。
S
Suragch
  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"); 

z
zl9394

如果您必须使用开关,请尝试此操作。

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

你也能解释一下吗..?
函数范围根据输入参数返回一些值,因此可以在这里进行“值范围”检测,加上switch case子句。
这适用于我的用例,我有 2 个 int 变量,我想检查 2 个变量是否在同一范围内,例如 (10-20),(20-30),.... 像这样
我建议使用枚举而不是魔法 int 值。
O
Oyzuu

或者您可以按预期使用您的单独案例并使用您的默认案例将范围指令指定为:

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 见下文默认值
L
Lubo

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

您也应该能够在整数上实现它。请注意,您的 switch 语句必须是详尽的(使用 default 关键字,或在 case 语句中使用所有可能的值)。


Ó
Óscar López

可以使用 switch 语句允许的 fall through 机制将多个条件分组在同一个 case 语句中,这在 Java tutorial 中有所提及,并在 {3 的第 §14.11. The switch Statement 节中详细说明}。

以下代码片段取自教程中的示例,它计算每个月的天数(从第 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;
}

G
Greg Kopff

不,你不能那样做。你能做的最好的就是

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

e
erickson

使用 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
@ChVas 此处设置地图的方式,floorEntry() 永远不会返回 null(插入 Integer.MIN_VALUE 键旨在防止这种情况发生)。但是,无论您的值类型如何,您都需要决定如何处理有效范围之外的键。
W
Williem

这是一个美丽而简约的方式

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

你能解释一下吗? ——我确实得到了“迷你ifs”,但不是那个idk。
@Tunaki 这是在级联中使用三元运算符(condition ? statementIfTrue : statementIfFalse)的 if..elseif 替代方案。
E
Elliott Frisch

您可以使用 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;
  }
}

A
Alexander Malakhov

@missingfaktor 的答案确实是正确的,但有点过于复杂。代码比它可能更冗长(至少对于连续间隔),并且需要重载/强制转换和/或长、浮点、整数等参数化

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

很抱歉回复晚了,我最近无法跟上 SO 回复。我会一一回复你的批评。 1. 代码有点冗长,是的,而且它也做了一些冗余计算。但在这种情况下,国际海事组织正在帮助澄清。在您的代码中,您必须记住前面的案例,因为您会从梯子上掉下来。
至于要求重载和强制转换,这不是一个有效的批评 IMO。 Java 没有明智的方法来抽象数字类型,这说明了 Java 的局限性,而不仅仅是这种方法。如果您想更好地理解这一点,您可能想探索 Haskell 的 Num 类型类。
@missingfaktor 1. 我想这是一个品味问题。在处理连续音程时,我个人喜欢将 if 视为逐渐溢出较低的子范围。此外,冗余计算根本不是问题,但冗余比较有点令人担忧:使相邻比较不同步变得更简单,例如在一些编辑之后:if (isBetween(x, 1, 4)) {...} else if (isBetween(x, 6, 10))。反正也没什么大不了的。
2. 同意 - Java 的限制,但这是我们必须使用的,您的原始代码将被复制用于各种类型。在这种特殊情况下,可以通过使用 Number 类来缓解问题,尽管 Haskell 的方法更好(从未真正学习过 Haskell,但它类似于 C++ 的“概念之光”。另外,我相信您的意思是 Real,而不是Num)。
C
ClassY

在阅读了所有评论后,我没有看到有人提到 enhanced switch 在这种情况下您可以有多个值 ->

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

并且由于在您的情况下,每种情况下只有一个表达式,因此您可以执行以下操作而无需break每种情况->

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

这是 Java 中增强开关的众多附加好处之一。


z
zemiak

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

i
isoplayer

Java 不支持这种类型的行为。但是,如果您有一个需要此功能的大型项目,请考虑在您的项目中混合 Groovy 代码。 Groovy 代码被编译成字节码,可以用 JVM 运行。我工作的公司使用 Groovy 编写服务类,使用 Java 编写其他所有内容。


w
wicas

出色的贡献。如果它仍然有用,我找到了一个选项来分析字符串中是否有不同于字母和空格的字符:

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;

在这个例子中,字母的 ASCII 码和“空格”ASCII 码被分组并用数字 0、1 或 2 表示。与上述不同的 ASCII 码被分组在值“99”中,所以我可以将有关它们的任何信息告知用户。