Java 有没有更有效的方法来编写多个if-else?

Java 有没有更有效的方法来编写多个if-else?,java,if-statement,range,code-duplication,Java,If Statement,Range,Code Duplication,我需要将平均分数与字母等级相匹配。这意味着 if (90 < avg && avg < 100) { return 'A'; } if(90=最小值和v.in范围(i)) .findAny(); } } 您可能会发现这种方法冗长且设计过度。是的 不过,我喜欢评分系统的定义方式 class Test { public static void main(String[] args) { Map<String, Predicate<In

我需要将平均分数与字母等级相匹配。这意味着

if (90 < avg && avg < 100) {
     return 'A';
} 
if(90
依此类推,直到'F',再加上5条if-else语句

这是大量重复,我匹配的范围长度相同


有没有更有效的方法?我不想将if-else语句重复5次。

您可以像下面的示例那样:

public static String avgValuetoGrade(int value) {
        int index = value/10;
        int gradeIndex = Math.max(0, index - 4);
        return (char)('F'-gradeIndex );
    }

首先将平均值除以10,得到数字0-9(整数除法)。接下来,您必须以某种方式将数字0-4减少为一个数字
-4
给出数字0-5并将0-4映射为0。然后您可以返回char(感谢@Carlos Heuberger)。

这将是以函数式编写的相同内容的一个示例。没有重复,但相当冗长

我不会使用它,除非乐队大小不同(如果可以的话)

Map rangeToGrade=Map.of(
范围。介于(90100),‘A’,
范围。介于(80,90),‘B’之间
//……其余的
);
整数分=50;
char grade=rangeToGrade.entrySet().stream()
.filter(e->e.getKey().contains(mark))
.map(map.Entry::getValue)
.findFirst()
.orElse(“?”);//或者抛出异常

来自Java9。例如,在Apache Commons中,我喜欢使用
枚举来解决此类问题

您只需在枚举值中定义范围并使用谓词

import java.util.*;

public class MyClass {
    public static void main(String args[]) {
      System.out.println(Letter.getValue(13)); // B
      System.out.println(Letter.getValue(28)); // C
      System.out.println(Letter.getValue(43)); // empty
    }
}

enum Letter {

    A(1, 10), B(11, 20), C(21, 30);

    int min;
    int max;

    Letter (int min, int max) {
        this.min = min;
        this.max = max;
    }

    boolean inRange(int v) {
        return v >= min && v <= max;
    }

    static Optional<Letter> getValue(int i) {
        return Arrays.stream(values())
           .filter(v -> v.inRange(i))
           .findAny();
    }

}
import java.util.*;
公共类MyClass{
公共静态void main(字符串参数[]){
System.out.println(Letter.getValue(13));//B
System.out.println(Letter.getValue(28));//C
System.out.println(Letter.getValue(43));//空
}
}
枚举字母{
A(1,10),B(11,20),C(21,30);
int-min;
int max;
字母(最小整数,最大整数){
this.min=min;
this.max=max;
}
布尔inRange(int v){
返回v>=最小值和v.in范围(i))
.findAny();
}
}

您可能会发现这种方法冗长且设计过度。是的

不过,我喜欢评分系统的定义方式

class Test {
  public static void main(String[] args) {
    Map<String, Predicate<Integer>> gradingSystem = new HashMap<>();

    gradingSystem.put("A", mark -> mark >= 90 && mark <= 100);
    gradingSystem.put("B", mark -> mark >= 80 && mark < 90);

    translateScoreIntoGrade(86, gradingSystem); // B
    translateScoreIntoGrade(95, gradingSystem); // A
  }

  public static String translateScoreIntoGrade(int score, Map<String, Predicate<Integer>> gradingSystem) {
    return gradingSystem.entrySet().stream()
        .filter(gradePredicate -> gradePredicate.getValue().test(score))
        .findFirst()
        .map(Map.Entry::getKey)
        .orElseThrow(() -> new IllegalArgumentException("This grade isn't valid for this system!"));
  }
} 
类测试{
公共静态void main(字符串[]args){
Map gradingSystem=new HashMap();
放坡系统(“A”,标记->标记>=90&&mark标记>=80&&mark<90);
TranslatesCoreinoGrade(86,分级系统);//B
TranslatesCoreinoGrade(95,分级系统);//A
}
公共静态字符串translateScoreIntoGrade(整数分数,地图分级系统){
return gradingSystem.entrySet().stream()
.filter(gradePredicate->gradePredicate.getValue().test(分数))
.findFirst()
.map(map.Entry::getKey)
.orelsetrow(()->新的IllegalArgumentException(“此等级对该系统无效!”);
}
} 

您可以将它映射到一个数组,避免分支预测规则,从而使它更高效,同时还可以保存if/else内容

class StackOverflow
{
    public static void main(String args[])
    {
        char grades[]={'A','B','C','D','E','F'};
        convert(grades,95);
        convert(grades,90);
        convert(grades,110);
        convert(grades,123);
        convert(grades,150);
    }
    static void convert(char grades[],int marks)
    {
        if(marks<=90||marks>=150)
        {
            System.out.println("Invalid marks");
            return;
        }
        int val=marks/10-9;
        System.out.println(grades[val]);
    }
}
类堆栈溢出
{
公共静态void main(字符串参数[])
{
字符等级[]={A',B',C',D',E',F'};
换算(95级);
转换(90级);
换算(110级);
转换(123级);
换算(150级);
}
静态无效转换(字符等级[],整数标记)
{
如果(分数=150)
{
System.out.println(“无效标记”);
回来
}
int val=分数/10-9;
系统输出打印LN(等级[val]);
}
}
注:假设91-99为A,100-109为B,110-119为C,依此类推。如果要避免数字100110等,只需在上面的If语句中添加规则|标记%10==0


希望这对您有所帮助:)

在Java版本12(启用预览)中,使用新的开关表达式来展示:

String grade = switch(avg/10) {
    case 9,10 -> "A";
    case 8    -> "B";
    case 7    -> "C";
    case 6    -> "D";
    case 5    -> "E";
    default   -> "F";
};
或者,非常灵活,如果不懒惰的话:

String grade = switch(avg) {
    case 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 -> "A";
    case 80, 81, 82, 83, 84, 85, 86, 87, 88, 89      -> "B";
    // you got the idea, I AM lazy
真实(?)解决方案:使用
NavigableMap
(示例
TreeMap
)及其
floorEntry()
lowerEntry()
方法:

NavigableMap<Integer, String> grades = new TreeMap<>();
grades.put(90, "A");
grades.put(80, "B"); 
...
// usage
String grade = grades.floorEntry(avg).getValue();
NavigableMap grades=new TreeMap();
评级。付诸表决(90,“A”);
(80,“B”);
...
//用法
字符串级别=grades.floorEntry(avg.getValue();

map中的值最终必须进行调整

注意:这是使用
Java8
进行的,不能访问
MapOf
,也不能使用外部库。也没有使用流来显示其他选项

我制作了一个
成绩册
类,当它被实例化时,
地图
的类字段将填充用于查找字母成绩的键。然后,您只需从
成绩册
中调用
.getGrade(int)
,对象也将处理负输入和大于100的输入,返回
N
。否则,它将从
地图
返回正确的等级

这更像是一种面向对象的方法,而不是使用
静态方法调用:

public class GradeBook {

    private Map<Integer, Character> map;

    public GradeBook() {
        constructMap();
    }

    public char getGrade(int grade) {
        if (grade >= 0 && grade <= 100) {
            return map.get(Math.max(0, grade/10 - 4));
        }
        else {
            return 'N';
        }
    }

    public void constructMap() {
        //You can use MapOf to add all of them at once in Java9+
        map = new HashMap<>();
        map.put(0, 'F');
        map.put(1, 'E');
        map.put(2, 'D');
        map.put(3, 'C');
        map.put(4, 'B');
        map.put(5, 'A');
        map.put(6, 'A');
    }

    public static void main(String [] args) {

        GradeBook grades = new GradeBook();

        //Testing different values
        System.out.println(grades.getGrade(100));
        System.out.println(grades.getGrade(75));
        System.out.println(grades.getGrade(80));
        System.out.println(grades.getGrade(91));
        System.out.println(grades.getGrade(45));
        System.out.println(grades.getGrade(2));
        System.out.println(grades.getGrade(-1));
    }
}

这种实现的缺点是第一次实现的时间稍长,但优点是很容易重用,因为您只需在任何需要的地方创建一个
新成绩册()

整数除以10,然后使用一个
开关
。这个问题正在@Triarion上讨论,如果
if
语句永远不会捕捉到10的倍数,这是有意的吗?,“90”是“a”还是“B”,那么100呢?这是比“a”更高的分数还是“a”?
if
语句有什么问题?什么样的答案,一个复杂的性能答案?一个容易理解的?名单还在继续……请看“或”。@NickA SO在这种情况下的一个技巧是根据答案调整问题,不管是谁做的。如果仅仅因为提问者的回答不对而忽略了有用的答案,那将是一件憾事。使用分数数组并通过数组中的索引获得分数将比使用
public class GradeBook {

    private Map<Integer, Character> map;

    public GradeBook() {
        constructMap();
    }

    public char getGrade(int grade) {
        if (grade >= 0 && grade <= 100) {
            return map.get(Math.max(0, grade/10 - 4));
        }
        else {
            return 'N';
        }
    }

    public void constructMap() {
        //You can use MapOf to add all of them at once in Java9+
        map = new HashMap<>();
        map.put(0, 'F');
        map.put(1, 'E');
        map.put(2, 'D');
        map.put(3, 'C');
        map.put(4, 'B');
        map.put(5, 'A');
        map.put(6, 'A');
    }

    public static void main(String [] args) {

        GradeBook grades = new GradeBook();

        //Testing different values
        System.out.println(grades.getGrade(100));
        System.out.println(grades.getGrade(75));
        System.out.println(grades.getGrade(80));
        System.out.println(grades.getGrade(91));
        System.out.println(grades.getGrade(45));
        System.out.println(grades.getGrade(2));
        System.out.println(grades.getGrade(-1));
    }
}
A
C
B
A
F
F
N