不打破合同就不可能实现真正的“改组比较器”。
Comparator合同的一个基本方面是,结果是可 重现的,
因此
Comparator必须确定特定实例的顺序。
当然,您可以使用混洗操作预先初始化该固定顺序,并创建一个比较器来精确地建立此顺序。例如
List<ElementType> ordering=new ArrayList<>(list);Collections.shuffle(ordering);list.sort(Comparator.comparingInt(ordering::indexOf));
虽然没有意义。显然,此比较器 不得 用于包含不在
ordering列表中的元素的集合。
或者,您可以使用没有排序顺序的值的稳定属性作为排序标准,例如哈希码。这可以通过稳定但可随机化的转换来增强,例如
public static Comparator<String> randomOrder() { ThreadLocalRandom r = ThreadLocalRandom.current(); int x = r.nextInt(), y = r.nextInt(); boolean b = r.nextBoolean(); return Comparator.comparingInt((String s)->s.hashCode()^x) .thenComparingInt(s->s.length()^y) .thenComparing(b? Comparator.naturalOrder(): Comparator.reverseOrder());}List<String> list=Arrays.asList("hello", "now", "shuffle", "this", "!");list.sort(randomOrder());System.out.println(list);list.sort(randomOrder());System.out.println(list);关键是每个
Comparator实例代表一个随机选择但固定的顺序,我们创建一个新
Comparator实例以请求不同的顺序。因此,没有
Comparator违反合同。
请注意,这
Comparator看起来有点复杂,因为它必须考虑可能的哈希冲突。然后它将诉诸于该
length属性(也是随机的),并且对于
String具有相同哈希码和长度的s,它将简单地退回到自然顺序或颠倒顺序,这不太可能引起注意,因为它仅影响这些罕见对的关系。
如果你创造价值这样的比较没有冲突(如
Integer实例)或覆盖它定义了平等的价值的所有属性(比如他们,
x和
y,的
Point),比较会显得简单得多。



