我有一个名为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;
}
答案 0 :(得分:2)
我会考虑的一个选项是将元素存储在一个类中,允许它们按类而不是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>
,则compareTo
中的Os
方法可能非常简单。使用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();
}
答案 1 :(得分:1)
你可以有一个返回BEFORE |的方法之后| INDETERMINATE(说),然后调用它。
result = newMethod(subresult);
if (result != INDETERMINATE) return result;
这并不是一个很大的改进,它仍然需要在任何地方重复,但它会更紧凑。
答案 2 :(得分:1)
由于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;
}