[英]Refactoring generic compareTo method
我有一個名為Os
的容器類,它可以包含不同的類型元素以及類Os
實例。 當我比較這堂課時,我想看看:
Os
元素的深度相等 我已確保類中包含的每個元素:
以下是我目前的情況。
例如,此測試用例將通過。
Os o1 = Os.of(3, 4d, Os.of("-"));
Os o2 = Os.of(Os.of(Character.toString('-')), 4.0, new Integer(3));
assertEquals(o1.toString(), "[3, 4.0, [-]]");
assertEquals(o2.toString(), "[[-], 4.0, 3]");
assertTrue(o1.reverse().compareTo(o2) == 0);
compareTo
方法:
@Override
public int compareTo(final Os that) {
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
int subresult = 0;
Comparable<?> othis;
Comparable<?> othat;
if (that == null)
return AFTER;
if (this == that)
return EQUAL;
subresult = ((Integer) this.o.size()).compareTo(that.o.size());
if (subresult < 0)
return BEFORE;
else if (subresult > 0)
return AFTER;
try {
for (int i = 0; i < this.o.size(); i++) {
othis = this.o.get(i);
othat = that.o.get(i);
if (othis.getClass() == othat.getClass()) {
if (othat instanceof Os) {
subresult = ((Os) othis).compareTo(((Os) othat));
if (subresult < 0)
return BEFORE;
else if (subresult > 0)
return AFTER;
} else {
subresult = hackCMP(othis, othat);
if (subresult < 0)
return BEFORE;
else if (subresult > 0)
return AFTER;
}
} else {
subresult = othis.getClass().getName()
.compareTo(othat.getClass().getName());
if (subresult < 0)
return BEFORE;
else if (subresult > 0)
return AFTER;
}
}
return EQUAL;
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return BEFORE;
}
private static int hackCMP(Object val, Object val2)
throws SecurityException, NoSuchMethodException,
IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
Method m = val.getClass().getMethod("compareTo", val.getClass());
return (Integer) m.invoke(val, val2);
}
我想重構代碼。
例如:
hackCMP
方法。 以下代碼段似乎重復很多。 我可以用什么代替它嗎?
subresult = <expression>; if (subresult < 0) return BEFORE; else if (subresult > 0) return AFTER; //else ...
我可以重構什么,怎么做?
@wolfcastle:數據存儲在private final ImmutableList<Comparable<?>> o;
。
我想提一下,每個答案都很有用。 以下似乎有效:
@Override
public int compareTo(final Os that) {
Ordering<Iterable<Comparable<?>>> order = //
Ordering.natural().<Comparable<?>> lexicographical();
int result = -1;
try {
result = ComparisonChain.start()
.compare(this.o.size(), that.o.size())
.compare(this.o, that.o, order).result();
} catch (Exception e) { //ignore: type mismatch
}
return result;
}
我會考慮的一種選擇是將元素存儲在一個類中,如果它們不是同一類,則允許按類而不是用compareTo
方法比較它們:
private static class Element implements Comparable<Element> {
// raw Comparable allows you to call compareTo
private final Comparable comparable;
Element(Comparable comparable) {
this.comparable = comparable;
}
@Override @SuppressWarnings("unchecked")
public int compareTo(Element o) {
Comparable other = o.comparable;
if(comparable.getClass().isInstance(other)) {
return comparable.compareTo(other);
}
return comparable.getClass().getName().compareTo(other.getClass().getName());
}
@Override
public boolean equals(Object obj) {
return obj instanceof Element && comparable.equals(((Element) obj).comparable);
}
@Override
public int hashCode() {
return comparable.hashCode();
}
@Override
public String toString() {
return comparable.toString();
}
}
然后,內部列表為List<Element>
,則Os
的compareTo
方法可能非常簡單。 使用Guava ,可能非常簡單:
@Override
public int compareTo(Os o) {
return ComparisonChain.start()
.compare(list.size(), o.list.size())
.compare(list, o.list, Ordering.natural().<Element>lexicographical())
.result();
}
您可能有一個返回BEFORE |的方法。 之后| INDETERMINATE(說),然后調用它。
result = newMethod(subresult);
if (result != INDETERMINATE) return result;
這並不是什么很大的改進,它仍然需要在所有地方重復,但是要更緊密一些。
由於List<Comparable<?>> o
屬性的泛型類型是不固定的,因此我將擺脫泛型類型並依賴原始類型。 它花費了一個@SuppressWarnings("rawtypes")
,但是將其最小化了。
@Override
@SuppressWarnings("rawtypes")
public int compareTo(final Os that) {
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
if (that == null)
return AFTER;
if (this == that)
return EQUAL;
int subresult = ((Integer) this.o.size()).compareTo(that.o.size());
if (subresult != EQUAL)
return subresult;
for (int i = 0; i < this.o.size(); i++) {
Comparable othis = this.o.get(i);
Comparable othat = that.o.get(i);
subresult = othis.compareTo(othat);
if (subresult != EQUAL)
return subresult;
}
return EQUAL;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.