Análisis del código fuente JDK del modo de estrategia en Comparator

Análisis de código fuente JDK

Comparator Modo de estrategia en. Hay un sort() método en la clase Arrays  , como sigue:


public class Arrays{
    public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }
}

Arrays es una clase de rol de entorno. El método de ordenación puede pasar una nueva estrategia para ordenar las matrices de acuerdo con esta estrategia.

Por ejemplo, la siguiente clase de prueba.


public class demo {
    public static void main(String[] args) {
​
        Integer[] data = {12, 2, 3, 2, 4, 5, 1};
        // 实现降序排序
        Arrays.sort(data, new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]
    }
}

Aquí, cuando llamamos al método sort de Arrays, el segundo parámetro se pasa al objeto de clase de subimplementación de la interfaz Comparator.

Por lo tanto, el Comparador actúa como un rol de estrategia abstracta, y la clase de sub-implementación concreta actúa como un rol de estrategia concreta.

Las clases de roles de entorno (matrices) deben llamarse con una referencia a la estrategia abstracta.

Entonces, ¿el método de clasificación de la clase Arrays usa los compare() métodos de la clase de subimplementación Comparator  ? Continuemos mirando los sort() métodos de la clase TimSort  ,

el código se muestra a continuación:

class TimSort<T> {
    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
                         T[] work, int workBase, int workLen) {
        assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
​
        int nRemaining  = hi - lo;
        if (nRemaining < 2)
            return;  // Arrays of size 0 and 1 are always sorted
​
        // If array is small, do a "mini-TimSort" with no merges
        if (nRemaining < MIN_MERGE) {
            int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
            binarySort(a, lo, hi, lo + initRunLen, c);
            return;
        }
        ...
    }   
        
    private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,Comparator<? super T> c) {
        assert lo < hi;
        int runHi = lo + 1;
        if (runHi == hi)
            return 1;
​
        // Find end of run, and reverse range if descending
        if (c.compare(a[runHi++], a[lo]) < 0) { // Descending
            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
                runHi++;
            reverseRange(a, lo, runHi);
        } else {                              // Ascending
            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)
                runHi++;
        }
​
        return runHi - lo;
    }
}

El código anterior eventualmente se encontrará con  countRunAndMakeAscending() este método.

Podemos ver que solo se usa el método de comparación,

Entonces, al llamar al método Arrays.sort, solo pase el objeto de clase del método de anulación de comparación específico.

Este también es un método que debe ser implementado por subclases en la interfaz Comparator.

Supongo que te gusta

Origin blog.csdn.net/qq_39368007/article/details/114028269
Recomendado
Clasificación