Java Comparable和Comparator

http://my.oschina.net/android520/blog/700738
public class ComparableUser implements Comparable<Object> {
	
	public String name;
	public int age;
	
	public ComparableUser(String name, int age) {
		this.name = name;
		this.age = age;
	}

	@Override
	public int compareTo(Object o) {
		return age - ((ComparableUser) o).age;
	}
}
ComparableUser[] users = new ComparableUser[] {
	new ComparableUser("Jim", 80),
	new ComparableUser("Tom", 10),
	new ComparableUser("Lily", 30),
	new ComparableUser("Marry", 20)
};
Arrays.sort(users);

Comparable interface, as long as the class inherits this interface, the sorting function of objects can be realized.



public class User {
	public String name;
	public int age;
	public User(String name, int age) {
		this.name = name;
		this.age = age;
	}
}
public class ComparatorUser implements Comparator<User> {
	@Override
	public int compare(User o1, User o2) {
		return o1.age - o2.age;
	}
}
User[] users2 = new User[] {
	new User("Jim", 80),
	new User("Tom", 10),
	new User("Lily", 30),
	new User("Marry", 20)
};
Arrays.sort(users2, new ComparatorUser());

The Comparator interface can be used to sort existing ones that do not inherit the Comparable interface.



The sort method is implemented differently in JDK6 and JDK7, as follows:

From http://blog.sina.com.cn/s/blog_8e6f1b330101h7fa.html

In Java 6, Arrays.sort() and Collections.sort() are used It is MergeSort, and in Java 7, the internal implementation is replaced by TimSort, which has stricter implementation requirements for comparison between objects:

Comparator implementations must ensure the following (from here):

a). sgn(compare(x, y)) == -sgn(compare(y, x))
b). (compare(x, y)>0) && (compare(y, z)>0) means compare(x, z)>0
c ). compare(x, y)==0 means that for any z: sgn(compare(x, z))==sgn(compare(y, z))

and in our code, a compare( ) implementation fragment is like this:

public int compare(ComparatorTest o1, ComparatorTest o2) {
    return o1.getValue() > o2.getValue() ? 1 : -1;
}


This violates the principle of a): suppose the value of X is 1, and the value of Y is also 1; then compare(X, Y) ≠ –compare(Y, X)
PS: TimSort is not only built in various JDK 7 versions, Also present in the Android SDK (although it doesn't use JDK 7).



Let's take a look at the specific sorting source code in the sort method

    static void sort(Object[] a, int lo, int hi) {
        rangeCheck(a.length, lo, hi);
        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);
            binarySort(a, lo, hi, lo + initRunLen);
            return;
        }
        ............................
    }

It can be seen from the code that binarySort is used for binary sorting

/**
     * Sorts the specified portion of the specified array using a binary
     * insertion sort.  This is the best method for sorting small numbers
     * of elements.  It requires O(n log n) compares, but O(n^2) data
     * movement (worst case).
     *
     * If the initial part of the specified range is already sorted,
     * this method can take advantage of it: the method assumes that the
     * elements from index {@code lo}, inclusive, to {@code start},
     * exclusive are already sorted.
     *
     * @param a the array in which a range is to be sorted
     * @param lo the index of the first element in the range to be sorted
     * @param hi the index after the last element in the range to be sorted
     * @param start the index of the first element in the range that is
     *        not already known to be sorted ({@code lo <= start <= hi})
     */
    @SuppressWarnings("fallthrough")
    private static void binarySort(Object[] a, int lo, int hi, int start) {
        assert lo <= start && start <= hi;
        if (start == lo)
            start++;
        for ( ; start < hi; start++) {
            @SuppressWarnings("unchecked")
            Comparable<Object> pivot = (Comparable) a[start];

            // Set left (and right) to the index where a[start] (pivot) belongs
            int left = lo;
            int right = start;
            assert left <= right;
            /*
             * Invariants:
             *   pivot >= all in [lo, left).
             *   pivot <  all in [right, start).
             */
            while (left < right) {
                int mid = (left + right) >>> 1;
                if (pivot.compareTo(a[mid]) < 0)
                    right = mid;
                else
                    left = mid + 1;
            }
            assert left == right;

            /*
             * The invariants still hold: pivot >= all in [lo, left) and
             * pivot < all in [left, start), so pivot belongs at left.  Note
             * that if there are elements equal to pivot, left points to the
             * first slot after them -- that's why this sort is stable.
             * Slide elements over to make room for pivot.
             */
            int n = start - left;  // The number of elements to move
            // Switch is just an optimization for arraycopy in default case
            switch (n) {
                case 2:  a[left + 2] = a[left + 1];
                case 1:  a[left + 1] = a[left];
                         break;
                default: System.arraycopy(a, left, a, left + 1, n);
            }
            a[left] = pivot;
        }
    }

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326840402&siteId=291194637