[英]What is the best way to optimize a function with many if-else statements(multiple conditions)?
What is the best approach or design pattern to optimize the code below?(I've thought about using switch statement but switch statement cannot handle multiple conditions in a single case.) 什么是优化下面代码的最佳方法或设计模式是什么?(我曾考虑过使用switch语句,但是switch语句无法在单个情况下处理多个条件。)
Below is the code snippet. 下面是代码片段。 Each major is determined by a certain numerical range. 每个专业都由某个数值范围确定。
public String getMajor(String major) {
crnCompare = Integer.parseInt(major);
if ((crnCompare >= 90702 && crnCompare <= 90733) || (crnCompare >= 10004 && crnCompare <= 10037)) {
this.major = "AC";
} else if ((crnCompare >= 10087 && crnCompare <= 10108) || (crnCompare >= 10471 && crnCompare <= 10482) || (crnCompare >= 90024 && crnCompare <= 90071)) {
this.major = "CS";
} else if ((crnCompare >= 10109 && crnCompare <= 10158) || (crnCompare >= 90072 && crnCompare <= 90116)) {
this.major = "EC";
} else if ((crnCompare >= 90117 && crnCompare <= 90203) || (crnCompare >= 10075 && crnCompare <= 10213) || (crnCompare >= 10498 && crnCompare <= 10572)) {
this.major = "EN";
} else if ((crnCompare >= 10038 && crnCompare <= 10040) || (crnCompare >= 10214 && crnCompare <= 10255) || (crnCompare >= 10256 && crnCompare <= 10260) || (crnCompare >= 90017 && crnCompare <= 90203) || crnCompare == 11172) {
this.major = "FI";
} else if ((crnCompare >= 90670 && crnCompare <= 90790) || (crnCompare >= 11236 && crnCompare <= 11239)) {
this.major = "FS";
} else if ((crnCompare >= 90253 && crnCompare <= 90273) || (crnCompare >= 90734 && crnCompare <= 90769) || (crnCompare >= 90274 && crnCompare <= 90360) || (crnCompare >= 10261 && crnCompare <= 10393)) {
this.major = "GB";
} else if ((crnCompare >= 100394 && crnCompare <= 10429) || (crnCompare >= 90361 && crnCompare <= 90398)) {
this.major = "GLS";
} else if ((crnCompare >= 10430 && crnCompare <= 10451) || (crnCompare >= 90399 && crnCompare <= 90420)) {
this.major = "HI";
} else if ((crnCompare >= 10452 && crnCompare <= 10468) || (crnCompare >= 90422 && crnCompare <= 90436) || crnCompare == 11119) {
this.major = "IDCC";
} else if ((crnCompare >= 9437 && crnCompare <= 90438) || (crnCompare >= 10469 && crnCompare <= 10470)) {
this.major = "IPM";
} else if ((crnCompare == 90421) || (crnCompare >= 11280 && crnCompare <= 11426)) {
this.major = "ID";
} else if ((crnCompare >= 90439 && crnCompare <= 90448) || (crnCompare >= 90483 && crnCompare <= 90497)) {
this.major = "LTF";
} else if ((crnCompare >= 90504 && crnCompare <= 90535) || (crnCompare >= 10573 && crnCompare <= 10596) || crnCompare == 90785) {
this.major = "MG";
} else if ((crnCompare >= 90536 && crnCompare <= 90553) || (crnCompare >= 10598 && crnCompare <= 10616) || crnCompare == 10740) {
this.major = "MK";
} else if ((crnCompare >= 90449 && crnCompare <= 90503) || (crnCompare >= 10514 && crnCompare <= 10564) || (crnCompare == 11120) || (crnCompare == 10555) || (crnCompare == 11127)) {
this.major = "MA";
} else if ((crnCompare >= 10637 && crnCompare <= 10715) || (crnCompare == 11142) || (crnCompare == 10739) || (crnCompare >= 90575 && crnCompare <= 90622)) {
this.major = "NAS";
} else if (crnCompare >= 90554 && crnCompare <= 90574 || crnCompare == 10617 || crnCompare == 10636) {
this.major = "ML";
} else if ((crnCompare >= 90623 && crnCompare <= 10646) || (crnCompare >= 10671 && crnCompare <= 10696)) {
this.major = "PI";
} else if ((crnCompare == 90647 || crnCompare == 90649) || (crnCompare >= 10697 && crnCompare <= 10698) || crnCompare == 10756) {
this.major = "PRS";
} else if ((crnCompare >= 11341 && crnCompare <= 11420)) {
this.major = "SL";
} else if ((crnCompare >= 90650 && crnCompare <= 90668) || (crnCompare >= 10716 && crnCompare <= 10734)) {
this.major = "SO";
} else if ((crnCompare == 10735)) {
this.major = "ST";
}
return this.major;
}
You might want to look into Guava's RangeMap
classes (other similar implementations are available). 您可能想研究Guava的RangeMap
类(其他类似的实现方式也可用)。
These allow you to express these conditions something like this: 这些使您可以表达这些条件,如下所示:
RangeMap<Integer, String> rangeMap =
ImmutableRangeMap.<Integer, String>builder()
.put(Range.closed(90702, 90733), "AC")
.put(Range.closed(10004, 10037), "AC")
.put(Range.closed(10087, 10108), "EN")
.put(Range.closed(10004, 10037), "AC")
// ...
.build();
Construct this once, and then query it like: 构造一次,然后查询如下:
String major = rangeMap.get(crmCompare);
There are a couple of advantage of this: 有两个优点:
The disadvantage is the addition of Guava, if you're not already using it. 缺点是添加了番石榴,如果您还没有使用过的话。
Standard table-driven approach: 标准表驱动方法:
public static class Range
{
// getters omitted for conciseness
int low;
int high;
String major;
public Range(int low, int high, String major)
{
this.low = low;
this.high = high;
this.major = major;
}
public boolean contains(int v)
{
return (v >= low && v <= high);
}
}
public static Range[] ranges = {
new Range(10004,10037,"AC"),
new Range(10087,10108,"AC"),
// etc
// Ideally this table is populated from a data file that can
// be updated at runtime without recompiling the code.
};
public String getMajor(String m)
{
int crnCompare = Integer.parseInt(m);
// Search for the matching range
for (Range r : ranges)
if (r.contains(crnCompare)) return r.major;
return null;
}
Encode all the conditions as a low-high pair and corresponding major code, and put all the conditions into an array. 将所有条件编码为低-高对和相应的主代码,然后将所有条件放入数组中。 To determine the major search the array to find the matching condition. 要确定主要搜索数组,以找到匹配条件。
Possible enhancements (left as an exercise) include 可能的增强(保留为练习)包括
I thought a while about this; 我想了一会儿。 focusing on the aspect of: "how can you make sure that your implementation is correct?" 关注以下方面:“如何确保实现正确?”
In that sense, I would have suggested a Range class, similar to the one proposed by Jim. 从这个意义上讲,我会建议一个Range类,类似于Jim提出的类。 Because such a class allows you to not only have a contains()
method closely associated to the range data; 因为这样的类使您不仅可以拥有一个与范围数据紧密相关的contains()
方法,而且还可以使您拥有一个与范围数据紧密相关的contains()
方法。 but on top of that, you could add methods like: 但最重要的是,您可以添加以下方法:
boolean isOverlapping(Range other)
... which you can use to detect situations when you didn't pay attention and you defined ranges that, well, overlap! boolean isOverlapping(Range other)
...可以用来检测不注意的情况,并且您定义的范围可以重叠! int compareTo(Range other)
... to implement the Comparable interface. int compareTo(Range other)
...实现Comparable接口。 And now you could sort ranges. 现在您可以对范围进行排序 。 Which would allow you to do binary search when the list of ranges for a certain "category" gets too large. 当某个“类别”的范围列表太大时,这将允许您执行二进制搜索。 But: I would not put that "major" name into the Range class; 但是:我不会将“主要”名称放到Range类中。 but the other way round: 但是反过来:
public enum RangeBasedMajor {
AC(Arrays.asList(new Range(90702, 90733), new Range(...)),
EN(...
private RangeBasedMajor(List<Range> ranges) ...
Key points here: 这里的重点:
Depending on your context, this might be overkill. 根据您的情况,这可能会过分杀伤力。 It really depends on how often you expect things to change in there; 这实际上取决于您期望事物在其中发生变化的频率。 and for example: if it is required to access/deal with that "major" information within other parts of the program. 例如:如果需要访问/处理程序其他部分中的“主要”信息。 When your requirement is only to map that number to a string (for example for printing something); 当您只需要将该数字映射到字符串时(例如用于打印内容); then that RangeMap is fine. 那么RangeMap就可以了。
But when you have other code that "deals" with "Majors" - then it might be worth looking into some of the suggestions I am making here. 但是,当您有其他代码与“专业”打交道时,那么值得在这里提出一些建议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.