Reputation: 185
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.)
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;
}
Upvotes: 1
Views: 366
Reputation: 140534
You might want to look into Guava's RangeMap
classes (other similar implementations are available).
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.
Upvotes: 6
Reputation: 140613
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. Because such a class allows you to not only have a contains()
method closely associated to the range data; 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!int compareTo(Range other)
... to implement the Comparable interface. 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; 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.
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.
Upvotes: 1
Reputation: 86774
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
Upvotes: 2