>source

다음을 수락하는 라이브러리 호출이 있다고 가정해 보겠습니다.

  1. 항목 목록(혼합/다중 유형T1,T2,T3,..) 및
  2. 맞춤 비교기,

그리고 일부 작업을 수행하는 것 외에도 허용하는 목록을 정렬합니다(먼저 유형별로, 다음으로 사용자 정의 비교기를 사용하여).

이제 다음 유형의 항목이 필요합니다.T1유형별로 정렬한 다음 맞춤 주문을 사용하고 다른 모든 유형의 항목(T2,T3,..) 유형만으로 정렬됨(즉, 유형별로 한 번 정렬되면 결과적으로 무작동, 순서 보존 비교기로만 정렬됨).

다시 말해, 이런 smth가 필요합니다(T1~이다java.lang.정수,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);
    }
}

위의 code를 실행하면 다음 출력이 생성됩니다.

[1, 1, 2, 3, 5, 8, 13, Lorem, ipsum, dolor, sit, amet, consectetur, adipiscing]

이제 둘 다 병합 정렬그리고 팀소트알고리즘(JDK에서 기본이 아닌 항목을 정렬하는 데 사용)은 다음과 같습니다. 안정적인, 주문을 보존해야 하는 쌍에 대해 맞춤 비교기가 0을 반환해도 괜찮습니까?

다른 대안이 있습니까?

"주문을 보존해야 하는 쌍에 대해 내 사용자 지정 비교기가 0을 반환해도 괜찮습니까?" 예.

kaya32021-11-19 02:51:11
  • 답변 # 1

    네, 하지만.

    두 가지 중요한 문제:

    1. 예, 비교기에는 '동일한 수준'이라는 개념이 있습니다. 즉, '동일한 hashCode() 및a.같음(b)는 사실이지만 비교자가 동일한 수준에 있음을 나타내는 경우(비교(a, b)== 0). 그러나 의미는 비교기를 사용하는 것에 달려 있습니다. 구체적으로 List.sort의 경우 이는 '동일한 수준'에 있는 모든 항목이 서로 옆에 있다는 것을 의미하며, 추가로 순서가 안정적이라는 의미입니다. . 하지만 이것이 바로 List의 정렬이 하는 일입니다.-예를 들어트리셋그러한 요소는 1개만 가질 수 있음을 나타냅니다. 비교자가 2개의 항목이 동일한 레벨에 있다고 말하면 TreeSet/TreeMap에 관한 한 동일합니다, 따라서 하나의 트리세트에 2개의 항목이 있을 수 없습니다.비교(a, b)== 0, 경우에도!a.같음(b). 따라서 이 질문에 대한 대답은 '예'이지만 이 '비교자는 동일한 수준에 있다고 말합니다'를 보편적으로 사용할 수는 없습니다.

    2. 비교자가 보고하는 것은 완벽하게 허용됩니다.비교(a, b)== 0동등하지 않은/b에 대한 것이지만 토론의 대상이 아닌다른 규칙이 있습니다. 모든비교자는 항상 이 규칙을 반드시준수해야 합니다. 이 작업을 수행하지 않으면 비교기를 사용하는 대상에 관계없이 문제가 발생합니다.

    • compare(a, a)== 0항상 유지해야 합니다.
    • 만약비교(a, b) < 0, 그 다음에비교(b, a) > 0항상 유지해야 합니다.
    • 만약비교(a, b) < 0그리고비교(b, c) < 0, 그 다음에비교(a, c) < 0유지해야 합니다.

    이 비교기:

    Comparator<Object> communism= (a, b) -> 0;
    

    이 모든 규칙을 준수하므로 그렇게 할 수 있습니다.

  • 답변 # 2

    예, 이러한비교기정렬을 위해목록.

    (그리고 매우 유사한 표현으로)는 다음을 요구합니다.

    목록의 모든 요소는 지정된 비교자를 사용하여 상호 비교할 수 있어야 합니다(즉, c.compare(e1, e2)는 목록의 e1 및 e2 요소에 대해 ClassCastException을 throw해서는 안 됨).

    그리고 계속

    이 정렬은 안정적임을 보장합니다. 동일한 요소는 정렬 결과로 재정렬되지 않습니다.

    에 대한 계약은 그러한 구현을 금지하는 추가 제한을 부과하지 않습니다. 단지 그러한 순서가 "같음"과 일치하지 않으므로 특정 지도 또는 세트와 함께 사용할 수 없다는 점만 주의할 뿐입니다.

  • 이전 Android 항목을 클릭하면 RecyclerView가 스크롤됩니다.
  • 다음 mysql : jdbcTemplate.update 다른 유형의 저장 프로 시저에 매개 변수 보내기