如何实现根据部分订单关系对其元素进行排序的java.util.Comparator
?
例如,给定部分订单关系 a ≺ c , b ≺ c ; a 和 b 的顺序未定义。
由于Comparator
需要总排序,因此实现会对部分排序未定义但是一致的元素进行排序。
以下是否有效?
interface Item {
boolean before(Item other);
}
class ItemPartialOrderComperator implements Comparator<Item> {
@Override
public int compare(Item o1, Item o2) {
if(o1.equals(o2)) { // Comparator returns 0 if and only if o1 and o2 are equal;
return 0;
}
if(o1.before(o2)) {
return -1;
}
if(o2.before(o1)) {
return +1;
}
return o1.hashCode() - o2.hashCode(); // Arbitrary order on hashcode
}
}
Comparators
是否需要传递?TreeMap
中使用时) 答案 0 :(得分:8)
它似乎更像是一个答案,而不是一个评论所以我会发布它
紧跟比较合同后,商是S上的等价关系,强加的排序是S的总订单。“
所以不,比较器需要总排序。如果您通过部分订购实现此操作,则违反了接口合同。
即使它可能在某些情况下有效,您也应该不尝试以违反接口合同的方式解决您的问题。
请参阅this question关于适合部分排序的数据结构。
答案 1 :(得分:8)
问题是,当你拥有无法比较的元素时,你需要回到比比较哈希码更聪明的东西。例如,给定部分顺序{a&lt; b,c&lt; d},哈希码可以满足h(d)&lt; h(b)&lt; h(c)&lt; h(a),表示&lt; b &lt; c&lt; d &lt; a(粗体表示由哈希码破坏的领带),这会导致TreeMap
出现问题。
一般情况下,除了事先对键进行拓扑排序之外,您可能无需做任何事情,因此欢迎您关注部分订单的一些细节。
答案 2 :(得分:2)
任何时候我都尝试使用哈希码来做这种事情,我后悔了。如果您的订购是确定性的,那么您会更高兴 - 如果没有别的话可用于调试。以下内容将通过为之前未遇到的任何Item
创建一个新索引,并在所有其他方法都失败的情况下使用这些索引进行比较。
请注意,订购仍不保证是可传递的。
class ItemPartialOrderComperator implements Comparator<Item> {
@Override
public int compare(Item o1, Item o2) {
if(o1.equals(o2)) {
return 0;
}
if(o1.before(o2)) {
return -1;
}
if(o2.before(o1)) {
return +1;
}
return getIndex(o1) - getIndex(o2);
}
private int getIndex(Item i) {
Integer result = indexMap.get(i);
if (result == null) {
indexMap.put(i, result = indexMap.size());
}
return result;
}
private Map<Item,Integer> indexMap = new HashMap<Item, Integer>();
}
答案 3 :(得分:1)
在jdk7中,您的对象将抛出运行时异常:
区域:API:实用工具 概要:数组和集合的更新排序行为可能会抛出 IllegalArgumentException 说明:
java.util.Arrays.sort
和({间接)java.util.Collections.sort
使用的排序算法已被替换 新的排序实现可能会抛出 IllegalArgumentException 检测违反Comparable合同的Comparable。该 以前的实现默默地忽略了这种情况。 如果需要先前的行为,则可以使用新的系统属性java.util.Arrays.useLegacyMergeSort
来恢复之前的行为 合并行为。
不相容的性质:行为
RFE: 6804124
答案 4 :(得分:0)
如果a < b
和b < c
暗示a < c
,那么您已使用hashCodes进行了总排序。拿a < d, d < c
。偏序表示b
和d
不一定是有序的。通过引入hashCodes,您可以提供排序。
示例:is-a-descendant-of(human,human)。
Adam (hash 42) < Moses (hash 17), Adam < Joe (hash 9)
蕴涵
Adam < Joe < Moses
一个反面的例子是相同的关系,但是当时间旅行允许成为你自己的后代时。
答案 5 :(得分:-1)
当一个项目不是&#34;之前&#34;也不是&#34;之后&#34;另一个,而不是返回哈希码的比较,只返回0
。结果将是&#34;总排序&#34;和&#34;任意&#34;订购重合项目。