重构通用的compareTo方法
我在做什么:
我有一个名为 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
方法。 -
以下代码段似乎多次重复。我可以用什么东西代替它吗?
子结果 = <表达式>; if(子结果<0) 返回之前; 否则如果(子结果> 0) 之后返回; //别的 ...
我可以重构什么以及如何重构?
编辑:
@wolfcastle:数据存储在 private final ImmutableList
。
我想提一下,每个答案都很有用。以下似乎有效:
@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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我考虑的一种选择是将元素存储在一个类中,如果它们不是同一类,则允许按类而不是通过其
compareTo
方法比较它们:然后,您的内部列表是一个
List
,您在Os
中的compareTo
方法可能非常简单。使用 Guava,它可能非常简单:One option I would consider would be storing the elements in a class that allows them to be compared by class rather than by their
compareTo
method if they aren't the same class:Then, with your internal list being a
List<Element>
, yourcompareTo
method inOs
could be pretty simple. Using Guava, it could be extremely simple:您可以有一个返回 BEFORE | 的方法。之后 |不确定(比如说),然后调用它。
这并没有多大的改进,仍然需要到处复制,只是更严格了一些。
You could have a method that returned BEFORE | AFTER | INDETERMINATE (say), then call it.
That's not much of an improvement, and it still needs to be duplicated everywhere, but it's a little tighter.
由于
List> 的泛型类型是o
属性不固定,我会摆脱通用类型并依赖原始类型。它花费一个@SuppressWarnings("rawtypes")
,但它减少了很多。Since the generic type of the
List<Comparable<?>> o
property is not fixed, I'd get rid of the generic type and rely on the raw type. It costs one@SuppressWarnings("rawtypes")
, but it minimizes a lot.