我有一个程序需要按以下顺序对匹配进行排序(以下是一个简短示例):
PIT
PREDICTIONS
Match 1
Match 2
Quarters 1 Match 1
Quarters 1 Match 2
Quarters 2 Match 1
Semis 1
Semis 2
Finals 1
Finals 2
注意:可以有无限的比赛,仅限1/4(无限子比赛),无限半决赛和无限决赛。
我有以下方法为上述标题之一分配分数:
public static long getMatchScore(String name) {
long score = 0;
String matchName = name.toLowerCase();
String[] tokens = matchName.split("\\s+");
if(matchName.startsWith("pit")) score -= 100000;
else if(matchName.startsWith("predictions")) score -= 1000;
else if(matchName.startsWith("quals")) score = Integer.parseInt(matchName.split("\\s+")[1]);
else if(matchName.startsWith("quarters")) {
if(Integer.parseInt(tokens[1]) == 1) score += 1000;
else if(Integer.parseInt(tokens[1]) == 2) score += 10000;
else if(Integer.parseInt(tokens[1]) == 3) score += 100000;
else if(Integer.parseInt(tokens[1]) == 4) score += 1000000;
score += Integer.parseInt(tokens[3]);
}
else if(matchName.startsWith("semis")) {
if(Integer.parseInt(tokens[1]) == 1) score += 10000000;
else if(Integer.parseInt(tokens[1]) == 2) score += 100000000;
score += Integer.parseInt(tokens[3]);
}
else if(matchName.startsWith("finals")) {
score += 1000000000;
score += Integer.parseInt(tokens[1]);
}
return score;
}
然后使用Java方法compareTo()
对其进行排序。有没有更好的方法来做到这一点,而不是分配像100000000
这样的大量数字。
答案 0 :(得分:2)
这个要求将代码中的逻辑嵌入到Comparable类中。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MatchDescription implements Comparable<MatchDescription> {
private MatchType matchType;
private int matchOrder = 0;
private int subMatchOrder = 0;
public MatchDescription(String name) {
String matchName = name.toLowerCase().trim();
String[] tokens = matchName.split("\\s+");
matchType = MatchType.getByName(tokens[0]);
if (matchType.hasMatchOrder()) {
matchOrder = Integer.parseInt(tokens[1]);
}
if (matchType.hasSubmatches()) {
subMatchOrder = Integer.parseInt(tokens[3]);
}
}
现在,使用匹配顺序,子顺序等逻辑覆盖方法compareTo(T)和equals(Object)。
@Override
public int compareTo(MatchDescription other) {
if (this.matchType == other.matchType)
if (this.matchOrder == other.matchOrder)
return (this.subMatchOrder - other.subMatchOrder);
else
return (this.matchOrder - other.matchOrder);
else
return (this.matchType.getMatchTypeOrder() - other.matchType.getMatchTypeOrder());
}
@Override
public boolean equals(Object other) {
return (other instanceof MatchDescription) &&
(((MatchDescription) other).matchType == this.matchType) &&
(((MatchDescription) other).matchOrder == this.matchOrder);
}
匹配类型通过内部枚举来管理:
private enum MatchType {
PIT("PIT", 1, false, false),
PREDICTIONS("PREDICTIONS", 2, false, false),
MATCH("Match", 3, true, false),
QUARTERS("Quarters", 4, true, true),
SEMIS("Semis", 5, true, true),
FINALS("Finals", 6, true, false)
;
private String name;
private int matchTypeOrder;
private boolean hasMatchOrder;
private boolean hasSubmatches;
MatchType(String name, int matchTypeOrder, boolean hasMatchOrder, boolean hasSubmatches) {
this.name = name;
this.matchTypeOrder = matchTypeOrder;
this.hasMatchOrder = hasMatchOrder;
this.hasSubmatches = hasSubmatches;
}
public boolean hasMatchOrder() {
return hasMatchOrder;
}
public boolean hasSubmatches() {
return hasSubmatches;
}
public static MatchType getByName(String matchName) {
for (MatchType value : values()) {
if (value.getName().equalsIgnoreCase(matchName))
return value;
}
return null;
}
private String getName() {
return name;
}
public int getMatchTypeOrder() {
return matchTypeOrder;
}
}
最后,toString()很好地呈现了对象:
public String toString() {
String description = matchType.getName();
if (matchType.hasMatchOrder()) {
description += " " + matchOrder;
if (matchType.hasSubmatches())
description += " Match " + subMatchOrder;
}
return description;
}
这是关于如何使用可比较对象的示例(注意还处理了空格):
public static void main(String[] args) {
String[] inputs = new String[] {
"PIT ",
" Finals 1 ",
"PREDICTIONS ",
" Match 2 ",
" Quarters 1 Match 1 ",
" Quarters 1 Match 2 ",
" Match 1 ",
" Semis 1 Match 1 ",
" Semis 2 Match 1",
" Finals 2",
" Quarters 2 Match 1 "};
List<MatchDescription> c = new ArrayList<>();
for (String input : inputs) {
c.add(new MatchDescription(input));
}
Collections.sort(c);
for (MatchDescription e : c) {
System.out.println(e);
}
}
}
答案 1 :(得分:1)
首先,我并没有讽刺地说,如果你要编写像getMatchScore
这样的代码,你应该花更多的时间学习如何编写干净的代码,而不是实际掏出更多代码。该方法的cyclomatic complexity是最重要的。
也就是说,如果我们认识到您的输入具有固有权重的组,例如Match
&lt; Quarters
,我们应该使用Enum
在代码中捕获它。一个具有整数权重的简单的就足够了,不需要像“隔壁的Java Guy”所示的复杂的一个。我测试过的以下代码如何工作?
private static final Comparator<String> BY_GROUP = (s1, s2) -> {
Map.Entry<Integer, Integer> e1 = toTuple(s1);
Map.Entry<Integer, Integer> e2 = toTuple(s2);
Comparator<Map.Entry<Integer, Integer>> c = Comparator.<Map.Entry<Integer, Integer>, Integer>comparing(Map.Entry::getKey)
.thenComparing(Map.Entry::getValue);
return c.compare(e1, e2);
};
private static Map.Entry<Integer, Integer> toTuple(String s) {
String[] tokens = s.toUpperCase().split("\\s");
Group group = Group.valueOf(tokens[0]);
int num = tokens.length > 1 ? Integer.valueOf(tokens[1]) : Integer.MIN_VALUE;
return new AbstractMap.SimpleImmutableEntry<>(group.weightage(), num);
}
private enum Group {
PIT(0), PREDICTIONS(1), MATCH(2), QUARTERS(3), SEMIS(4), FINALS(5);
private int weightage;
Group(int weightage) {
this.weightage = weightage;
}
public int weightage() {
return this.weightage;
}
}
public static void main(String[] args) {
List<String> input = Arrays.asList("PIT", "PREDICTIONS", "Match 1", "Match 2",
"Quarters 1 Match 1", "Quarters 1 Match 2", "Quarters 2 Match 1", "Semis 1", "Semis 2",
"Finals 1", "Finals 2");
input.sort(BY_GROUP);
System.out.println(input);
}
答案 2 :(得分:0)
第一件事:给定的代码确实包含重复的代码。这本身就是一件坏事。但也是一个小的性能打击。
示例:您正在调用parseInt(token [0])5次或更多次。您可以重构整个方法以使其更容易阅读和B)例如仅计算一次表达式。