考慮我有一個庫呼叫它接受:
- 專案的串列(混合/多種型別的
T1,T2,T3,和,..) - 自定義比較器
C,
并且,除了做一些作業之外,對它接受的串列進行排序(首先按型別,然后使用自定義比較器C)。
現在,我需要型別的專案T1分類按型別,然后使用自定義的順序,而所有其他型別的專案(T2,T3,...)排序型別只(即一旦按型別排序,因此只能用無操作排序,保持順序的比較器)。
換句話說,我需要這樣的東西(T1是java.lang.Integer,T2是java.lang.String):
import java.util.Comparator;
import java.util.List;
import static java.util.Arrays.asList;
import static java.util.Comparator.comparing;
import static java.util.Comparator.comparingInt;
class C {
/**
* The library call.
*/
static <T> void processAndSort(final List<T> items,
final Comparator<? super T> secondaryComparator) {
final Comparator<T> typeComparator = comparing(it -> it.getClass().getName());
items.sort(typeComparator.thenComparing(secondaryComparator));
// Do some extra work.
}
public static void main(final String ... args) {
final List<?> items = asList(13, "Lorem",
8, "ipsum",
5, "dolor",
3, "sit",
2, "amet",
1, "consectetur",
1, "adipiscing");
processAndSort(items, (final var left, final var right) -> {
final Class<?> clazz = left.getClass();
/*
* Should be already sorted by type.
*/
if (!clazz.equals(right.getClass())) {
throw new IllegalStateException();
}
if (clazz.equals(Integer.class)) {
/*
* Compare integers using a custom comparator.
*/
return comparingInt(Integer::intValue).compare((Integer) left, (Integer) right);
}
/*
* For all other types, retain the original order.
*/
return 0;
});
System.out.println(items);
}
}
上面的代碼在運行時將產生以下輸出:
[1, 1, 2, 3, 5, 8, 13, Lorem, ipsum, dolor, sit, amet, consectetur, adipiscing]
現在,假設Merge Sort和Timsort演算法(由 JDK 用于對非原語進行排序)都是穩定的,我的自定義比較器是否可以為應保留順序的對回傳0?
是否存在其他替代方案?
uj5u.com熱心網友回復:
是的,可以使用這樣的 aComparator對a進行排序List。
Collections.sort()(并且List.sort()措辭非常相似)只要求
串列中的所有元素必須使用指定的比較器相互比較(即,對于串列中的任何元素 e1 和 e2,c.compare(e1, e2) 不得拋出 ClassCastException)。
然后繼續
這種排序保證是穩定的:相等的元素不會因排序而重新排序。
合同也沒有Comparator強加任何進一步的限制來禁止這樣的實作——它只是警告這樣的順序不“與平等一致”,因此不能與某些地圖或集合一起使用。
uj5u.com熱心網友回復:
對,但是。
兩個重要的問題:
是的,比較器具有“在相同級別”的概念,意思是:在“相同 hashCode() 并且
a.equals(b)為真”意義上不一定相等的物件,但比較器表明它們處于同一級別 (compare(a, b) == 0)。然而,這意味著什么取決于使用比較器的東西。具體對于 List.sort 而言,這僅意味著“處于同一級別”的所有內容都將彼此相鄰,而且排序是穩定的,這意味著,在您開始排序之前它們的排序是它們之后的順序. 但這正是 List 的排序所做的- 例如TreeSet宣告你只能有 1 個這樣的元素;如果比較器表示 2 個專案在同一級別,就 TreeSet/TreeMap 而言,它們是相等的,因此您不能在一個樹集中有 2 個專案 whichcompare(a, b) == 0,即使!a.equals(b). 因此,雖然這個問題的答案是“是”,但請注意,您不能普遍使用這個“比較器表示它們處于同一水平”。比較器報告
compare(a, b) == 0不相等的 a/b是完全可以接受的,但還有其他規則沒有討論。所有比較者必須始終遵守這些規則;無論您將比較器用于什么目的,都無法做到這一點:
compare(a, a) == 0必須始終持有。- 如果
compare(a, b) < 0,則compare(b, a) > 0必須始終保持。 - 如果
compare(a, b) < 0和compare(b, c) < 0,則compare(a, c) < 0必須成立。
這個比較器:
Comparator<Object> communism = (a, b) -> 0;
確實遵守所有這些規則,所以,當然,你可以做到。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/359770.html
下一篇:按降序對陣列的數字進行排序
