【发布时间】:2015-06-11 06:53:06
【问题描述】:
我编写了一个小型列表排序器,它使用Key 对象从可比较形式的对象中提取特定的“键”。然后排序器依次按照所有键对列表进行排序。
排序器可以使用对给定类型对象起作用的任何组键进行排序。每个键都能够处理一种类型的对象,并且总是返回相同类型的可比较值。
class Sorter {
public interface Key<T, V extends Comparable<V>> {
public V get(T t);
}
static <T> void sort(List<T> data, final Key<T, ?> key[], final int dir[]) {
Collections.sort(list, new Comparator<T>() {
public int compare(T a, T b) {
for (int i = 0; i < key.length; i++) {
final Comparable av = key[i].get(a), bv = key[i].get(b);
final int cmp = av.compareTo(bv);
if (cmp != 0) return cmp * dir[i];
}
return 0;
}
});
}
}
因此,例如,您可以拥有一个提取 String(即 Comparable)的 JSONStringKey,并且您可以拥有一个单独的 JSONNumericKey 提取 Double)(这也是 @ 987654328@)。永远不会比较来自两个不同键的值,但会比较两个不同对象中的相同键。
class JSONStringKey extends Sorter.Key<JSONObject, String> {
final String key;
JSONStringKey(String key) {this.key = key;}
public String get(JSONObject o) {return o.optString(key);}
}
class JSONNumericKey extends Sorter.Key<JSONObject, Double> {
final String key;
JSONNumericKey(String key) {this.key = key;}
public Double get(JSONObject o) {return o.optDouble(key);}
}
...
// sort by price descending then name ascending
final Key<JSONObject, ?> keys[] = { new JSONNumericKey("price"), new JSONStringKey("name") };
sort(list, keys, new int[]{-1, 1});
Java 在排序器中警告这一行:
final Comparable av = key[i].get(a), bv = key[i].get(b);
它警告 av 和 bv 使用原始类型声明:Comparable 而不是 Comparable<?>。他们是。但是如果我把类型改成Comparable<?>,那么下一行av.compareTo(bv)就失败了,因为两个不同的Comparable<?>不一定是同一个类型。在我的具体实现中,它们将是,但我不知道如何将其表达给类型系统。
如何告诉类型系统av 和bv 具有完全相同的类型?我无法通过给出特定类型(例如Comparable<String>)来“修复”它,因为在我的示例中,循环中的第一个键返回String(实现Comparable<String>),循环中的第二个键返回@ 987654343@(实现Comparable<Double>)。
我可以在key[i].get() 行上写@SuppressWarnings("rawtypes"),在av.compareTo(bv) 行上写@SuppressWarnings("unchecked"),但我希望尽可能检查类型。
编辑:感谢 davmac 的回答,创建一个固定到特定可比较类型的中间方法可以正常工作:
public int compare(T a, T b) {
for (int i = 0; i < key.length; i++) {
final int cmp = compareKey(key[i], a, b);
if (cmp != 0) return cmp * dir[i];
}
}
private <V extends Comparable<V>> compareKey(Key<T, V> key, T a, T b) {
final V av = key.get(a), bv = key.get(b);
return av.compareTo(bv);
}
【问题讨论】: