有没有更有效的方法来编写多个if else?
Is there a more efficient way to write multiple if else?
我需要将平均分与字母等级相匹配。这意味着
if (90 < avg && avg < 100) {
return 'A';
}
等等,直到 '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。然后你可以 return 字符(感谢@Carlos豪伯格)。
这将是同一事物以函数式风格编写的示例。没有重复,但是很啰嗦
我不会使用它,除非乐队的大小不同(你可以 )
Map<Range<Integer>, Character> rangeToGrade = Map.of(
Range.between(90, 100), 'A',
Range.between(80, 90), 'B'
//... the rest
);
int mark = 50;
char grade = rangeToGrade.entrySet().stream()
.filter(e -> e.getKey().contains(mark))
.map(Map.Entry::getValue)
.findFirst()
.orElse('?'); // or throw an exception
我喜欢用enum
来解决这类问题。
您只需在枚举值中定义您的范围并使用谓词。
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();
}
}
您可能会发现这种方法冗长且设计过度。是的,它就是。
不过,我喜欢评分系统的定义方式。
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!"));
}
}
你可以将它映射到一个数组,避免分支预测规则,从而提高效率,同时节省 if/else 东西。
class Whosebug
{
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]);
}
}
注意:这里假设91-99是A,100-109是B,110-119是C 等等。如果您想避免使用数字 100,110 等,只需在上面的 if 语句中添加规则 ||marks%10==0。
希望这对您有所帮助:)
为了炫耀,在 Java 版本 12(启用预览)中,使用新的 Switch 表达式:
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();
地图中的值最终必须调整
注意: 这是使用 Java 8
制作的,无法访问 MapOf
并且不使用外部库。也没有使用 Streams 来显示其他选项。
我做了一个 GradeBook
class ,当它被实例化时, Map
的 class 字段填充了用于查找字母等级的键。然后,您可以从 GradeBook
对象调用 .getGrade(int)
,同时处理负输入和输入超过 100 且 return 为 N
的情况。否则它将 return 来自 Map
的正确等级。
这更像是一种面向对象的方法,而不是使用 static
方法调用:
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
这个实现的缺点是第一次实现有点长,但好处是它很容易重用,因为你只需要在任何你需要的地方创建一个 new GradeBook()
。
我需要将平均分与字母等级相匹配。这意味着
if (90 < avg && avg < 100) {
return 'A';
}
等等,直到 '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。然后你可以 return 字符(感谢@Carlos豪伯格)。
这将是同一事物以函数式风格编写的示例。没有重复,但是很啰嗦
我不会使用它,除非乐队的大小不同(你可以
Map<Range<Integer>, Character> rangeToGrade = Map.of(
Range.between(90, 100), 'A',
Range.between(80, 90), 'B'
//... the rest
);
int mark = 50;
char grade = rangeToGrade.entrySet().stream()
.filter(e -> e.getKey().contains(mark))
.map(Map.Entry::getValue)
.findFirst()
.orElse('?'); // or throw an exception
我喜欢用enum
来解决这类问题。
您只需在枚举值中定义您的范围并使用谓词。
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();
}
}
您可能会发现这种方法冗长且设计过度。是的,它就是。
不过,我喜欢评分系统的定义方式。
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!"));
}
}
你可以将它映射到一个数组,避免分支预测规则,从而提高效率,同时节省 if/else 东西。
class Whosebug
{
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]);
}
}
注意:这里假设91-99是A,100-109是B,110-119是C 等等。如果您想避免使用数字 100,110 等,只需在上面的 if 语句中添加规则 ||marks%10==0。
希望这对您有所帮助:)
为了炫耀,在 Java 版本 12(启用预览)中,使用新的 Switch 表达式:
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();
地图中的值最终必须调整
注意: 这是使用 Java 8
制作的,无法访问 MapOf
并且不使用外部库。也没有使用 Streams 来显示其他选项。
我做了一个 GradeBook
class ,当它被实例化时, Map
的 class 字段填充了用于查找字母等级的键。然后,您可以从 GradeBook
对象调用 .getGrade(int)
,同时处理负输入和输入超过 100 且 return 为 N
的情况。否则它将 return 来自 Map
的正确等级。
这更像是一种面向对象的方法,而不是使用 static
方法调用:
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
这个实现的缺点是第一次实现有点长,但好处是它很容易重用,因为你只需要在任何你需要的地方创建一个 new GradeBook()
。