JDK source code analysis of the strategy mode in Comparator

JDK source code analysis

Comparator Strategy mode in. There is a sort() method in the Arrays class  , as follows:


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 is an environment role class. The sort method can pass a new strategy to sort Arrays according to this strategy.

For example, the following test class.


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]
    }
}

Here, when we call the sort method of Arrays, the second parameter is passed the sub-implementation class object of the Comparator interface.

So the Comparator acts as an abstract strategy role, and the concrete sub-implementation class acts as a concrete strategy role.

The environment role class (Arrays) should be called with a reference to the abstract strategy.

So, does the sort method of the Arrays class use the compare() methods in the Comparator sub-implementation class  ? Let us continue to look at the sort() methods of the TimSort class  ,

code show as below:

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;
    }
}

The above code will eventually run into  countRunAndMakeAscending() this method.

We can see that only the compare method is used,

So when calling the Arrays.sort method, only pass the class object of the specific compare override method.

This is also a method that must be implemented by subclasses in the Comparator interface.

Guess you like

Origin blog.csdn.net/qq_39368007/article/details/114028269