Java object sorting, Chinese sorting, sortedset sorting usage, and source code explanation

Source: Internet
Author: User
Tags collator comparable

There are many sorting algorithms in C and C ++, but usually the sorting algorithm has to put programmers into an understanding of many pointers and positions at the underlying layer during code writing. Java does not want this, therefore, most sorting tasks can be done by Java. For example, if you want to sort an array, you can use:Collections. Sort (list)The list will be sorted.Arrays. SortSo the array is naturally usedArrays. SortAndSortedsetThe sorting function is also implemented in a similar way, but the related methods are called internally. sortedset is only an interface and there are many implementation classes. This article usesTreesetImplementation class as an example.

 

However, there must be a comparison size for sorting, so the information transmitted, through which Java compares the size?ComparetoIn this case, the data needs to be convertedComparableSo your object needs implementscomparable and implements the internal method compareto. As long as your compareto implementation is what you want, the Sorting must be correct, if there are other methods, some, you can pass in a comparison class during sorting, because this can also reduce the possibility of null pointers. The passed classes need to be implemented:ComparatorInterface to implement its method: Compare class, although the equals method defined in the interface does not need to worry about it, because the object has been implemented, the equals method is not used in the internal sorting.

 

The following example is used to sort Chinese characters and objects respectively, and the object is used respectively.ComparableInterface, and the implementation of separately defining sorting objectsComparatorInterface to complete sorting:

 

Instance 1 (sort Chinese using the comparator Interface ):

Import Java. text. collator; import Java. util. arrays; import Java. util. collections; import Java. util. comparator; import Java. util. list; public class chinesesortcompare {@ suppresswarnings ("rawtypes") Private Final Static comparator china_compare = collator. getinstance (Java. util. locale. china); public static void main (string [] ARGs) {sortarray (); sortlist (); system. out. println ("Li Si ". compareto ("Zhang San"); // if the former is greater than the latter, it is a positive number; otherwise, it is a negative number, equal to 0} @ suppresswarnings ("unchecked") Private Static void sortlist () {list <string> List = arrays. aslist ("Zhang San", "Li Si", "Wang Wu"); collections. sort (list, china_compare); For (string STR: List) {system. out. println (STR) ;}@suppresswarnings ("unchecked") Private Static void sortarray () {string [] arr = {"James", "Lee", "Wang Wu "}; arrays. sort (ARR, china_compare); For (string STR: ARR) {system. out. println (STR );}}}

We can see that the output results are the same. Of course, the string itself has the compare method, and it also implementsComparableInterface, so if you do not putChina_compareFor processingStringYour ownComparetoFor sorting, the sorting result is naturally not what you want, of course, English should be what you want.

 

Instance 2 (sort objects by using external comparator definition ):

 

First, we need to construct an object class. For simplicity, we use two attributes to define a class like userdo, which is described as follows:

public class UserDO {protected String name;protected String email;public UserDO() {}public UserDO(String name , String email) {this.name = name;this.email = email;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}}

Two attributes are defined: name and email. In this case, we want to sort by name. Then we define the sorting class as follows:

import java.text.Collator;import java.util.Comparator;public class UserDOComparator implements Comparator<UserDO> {Collator cmp = Collator.getInstance(java.util.Locale.CHINA);@Overridepublic int compare(UserDO userDO1, UserDO userDO2) {return cmp.compare(userDO1.getName(), userDO2.getName());}}

Now we can see that we have implemented the compare method, which uses pinyin sorting. Then we can simulate some data verification results:

Import Java. util. arrays; import Java. util. collections; import Java. util. list; import Java. util. sortedset; import Java. util. treeset; public class sortuserlisttest {private final static userdocomparator user_comparator = new userdocomparator (); public static void main (string [] ARGs) {sortuserdoarray (); sortuserdolist (); sortuserbysortedset ();} Private Static void sortuserbysortedset () {sortedset <userdo> userset = new treeset <userdo> (user_comparator); userset. add (New userdo ("Zhang San", "aaazhangsan@ddd.com"); userset. add (New userdo ("Li Si", "ddlisi@dsfds.com"); userset. add (New userdo ("Wang Wu", "ddwangwu@fsadfads.com"); For (userdo: userset) {system. out. println (userdo. getname () ;}} Private Static void sortuserdolist () {list <userdo> List = arrays. aslist (New userdo ("Zhang San", "aaazhangsan@ddd.com"), new userdo ("Li Si", "ddlisi@dsfds.com"), new userdo ("Wang Wu", "ddwangwu@fsadfads.com ")); collections. sort (list, user_comparator); For (userdo: List) {system. out. println (userdo. getname () ;}} Private Static void sortuserdoarray () {userdo [] userdoarray = new userdo [] {New userdo ("James", "aaazhangsan@ddd.com "), new userdo ("Li Si", "ddlisi@dsfds.com"), new userdo ("Wang Wu", "ddwangwu@fsadfads.com")}; arrays. sort (userdoarray, user_comparator); For (userdo: userdoarray) {system. out. println (userdo. getname ());}}}

Based on these inputs, you can see that the output is consistent with the actual pinyin sorting by name. Someone will ask, if I sort by two fields, first, sort by one field, then sort by another field. Second, how should we perform flashback, in actual flashback, you only need to change the original output to the opposite number in the compare method. The compare result is positive, negative, or 0. If it is positive, it indicates that the first data is larger than the second data, while the negative number is the opposite. If the value is 0, it indicates equal. The same is true for multi-field sorting. After sorting at the first layer, the result is obtained to see if it is 0, if it is 0, then sort by the second field. Otherwise, the result returned by the first layer is directly returned. The hybrid application of the two and multi-layer sorting are implemented.

 

Instance 3 (sort the above userdo by usercomparabledo on the basis of the Class)

First, rewrite userdo as usercomparabledo:

import java.text.Collator;import java.util.Comparator;public class UserComparableDO extends UserDO implements Comparable<UserDO> {    public UserComparableDO() {}public UserComparableDO(String name , String email) {this.name = name;this.email = email;}@SuppressWarnings("rawtypes")private final static Comparator CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA);@SuppressWarnings("unchecked")@Overridepublic int compareTo(UserDO userDO) {return CHINA_COMPARE.compare(this.getName(), userDO.getName());}}

Of course, it is incorrect to define a comparator directly in this Code. This is generally abstracted into some common commons components of the system. Secondly, if there is no userdo class, you can write the corresponding attributes once. I have all the userdo directly integrated here, reducing a lot of code.

 

In this case, you do not need to write a comparator, so you can directly sort it. below is our test program:

Import Java. util. arrays; import Java. util. collections; import Java. util. list; import Java. util. sortedset; import Java. util. treeset; public class sortuserlistbycomparable {public static void main (string [] ARGs) {sortuserbysortedset (); sortuserdolist (); sortuserdoarray ();} Private Static void sortuserbysortedset () {sortedset <usercomparabledo> userset = new treeset <usercomparabledo> (); userset. add (New usercomparabledo ("Michael", "aaazhangsan@ddd.com"); userset. add (New usercomparabledo ("", "ddlisi@dsfds.com"); userset. add (New usercomparabledo ("", "ddwangwu@fsadfads.com"); For (usercomparabledo userdo: userset) {system. out. println (userdo. getname () ;}} Private Static void sortuserdolist () {list <usercomparabledo> List = arrays. aslist (New usercomparabledo ("Zhang San", "aaazhangsan@ddd.com"), new usercomparabledo ("Li Si", "ddlisi@dsfds.com"), new usercomparabledo ("Wang Wu", "ddwangwu@fsadfads.com ")); collections. sort (list); For (usercomparabledo userdo: List) {system. out. println (userdo. getname () ;}} Private Static void sortuserdoarray () {usercomparabledo [] userdoarray = new usercomparabledo [] {New usercomparabledo ("John", "aaazhangsan@ddd.com "), new usercomparabledo ("Li Si", "ddlisi@dsfds.com"), new usercomparabledo ("Wang Wu", "ddwangwu@fsadfads.com")}; arrays. sort (userdoarray); For (usercomparabledo userdo: userdoarray) {system. out. println (userdo. getname ());}}}

We can see that the custom comparator is no longer used as the parameter in this sorting, and the treeset entry parameters are not passed in.

 

The result is clear. Let's look at the relevant source code to confirm this statement. First, let's look at the collections. sort method:

Source code snippet 1: collections. Sort (list <t> List)

public static <T extends Comparable<? super T>> void sort(List<T> list) {Object[] a = list.toArray();Arrays.sort(a);ListIterator<T> i = list.listIterator();for (int j=0; j<a.length; j++) {    i.next();    i.set((T)a[j]);}}

In this caseArrays. Sort ()After sorting, write the array data back to the list. In addition, according to the definition of the method, generic t requires that the incoming class must beComparableClass subclass or implementation class, so you need to callCollections. Sort (list)In this method, each row of data in the input list must beImplements comparableThis interface. Otherwise, an error will be reported during compilation.

 

Let's look at the overload method and pass in the Custom comparator.

Source code snippet 2: collections. Sort (list <t> list, comparator <? Super T> C)

public static <T> void sort(List<T> list, Comparator<? super T> c) {Object[] a = list.toArray();Arrays.sort(a, (Comparator)c);ListIterator i = list.listIterator();for (int j=0; j<a.length; j++) {    i.next();    i.set(a[j]);}}

It is also similar to the first method, that is, the corresponding overload method of arrays. sort is called. It seems that it is implemented in arrays, so let's look at it further:

 

Source code snippet 3: arrays. Sort (T [] T ):

public static void sort(Object[] a) {        Object[] aux = (Object[])a.clone();        mergeSort(aux, a, 0, a.length, 0);}

It seems that the code snippet is handed overMergesortThe array is cloned and used as the basic data for sorting. The original array as the sorting target should be the core part of mergesort code snippet. We put it here first, let's take a look at another sort overload method. Note that there is no such thingCollections. Sort (list <t> List)In this way, the type is checked during compilation, that is, when this method is used, each row in the array does not exist.Implements comparableWill there be any errors, but an error will be reported during the runtime, which will be described in the following source code.

 

Source code segment 4: arrays. Sort (T [] T, comparator <? Super T> C)

    public static <T> void sort(T[] a, Comparator<? super T> c) {T[] aux = (T[])a.clone();        if (c==null)            mergeSort(aux, a, 0, a.length, 0);        else            mergeSort(aux, a, 0, a.length, 0, c);    }

Mergesort is also overloaded, that is, when a custom comparator is passed in and a custom comparator is not passed in, different methods are called for implementation, then let's look at the implementation of the two methods.

 

Source code snippet 5: mergesort (object [] SRC, object [] DST, int low, int high, int off)

private static void mergeSort(Object[] src,  Object[] dest,  int low,  int high,  int off) {int length = high - low;        if (length < INSERTIONSORT_THRESHOLD) {            for (int i=low; i

After carefully reading the code, we can find that sorting is performed by recursive callback (note the changes of the low and high parameters in the middle). If the size of each segment is greaterInsertionsort_threshold (defined as 7)When the time is reached, the segments are segmented, the first and the last segments are separated, and then the two segments are called for recursion. After recursion, the data is sorted again, the two segments are considered to be completely ordered. If not, sort the two segments again, and then sort them well, because the two segments are sorted well, therefore, there is no need for two loops. You only need to scan them cyclically. The two arrays go down in order to compare the minimum values and write them to the array, larger users do not write the array to compare with the next value of another array, and write the last piece of data (which is determined by cross-border in the source code) to the tail:

     for(int i = destLow, p = low, q = mid; i < destHigh; i++) {            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)                dest[i] = src[p++];            else                dest[i] = src[q++];     }

The sorting of two ordered arrays is a classic writing method, mainly the concentration of the IF statement, otherwise the code will be very long.

 

Note:: In code sorting, forced type conversion to comparable is used to call the internal comareto method. Therefore, if your class does not haveImplements comparableWhen collecting collections. Sort (list <t> list), an error will be reported during compilation. As mentioned aboveArrays. Sort (object [] T)No error is reported during compilation, but the error is:Java. Lang. classcastexceptionXxxdo
Cannot be cast to Java. Lang. Comparable

 

In the sorting part, let's take a look at its overloaded mergesort method, which is to pass in the Custom comparator method.

Source code snippet 6: mergesort (object [] SRC, object [] DST, int low, int high, 0000ff, comparator C)

   private static void mergeSort(Object[] src,  Object[] dest,  int low, int high, int off,  Comparator c) {int length = high - low;if (length < INSERTIONSORT_THRESHOLD) {    for (int i=low; i

It can be found that the algorithm is exactly the same as the previous method. The only difference is that the Compare used in sorting is changed to the comparator passed in, and there is no difference between the rest.

 

It is clear that the sorting provided by Java is still relatively efficient. In most cases, you do not need to write the Sorting Algorithm by yourself, finally, let's take a look at how to sort in the treeset when adding. comparator and not passed in, respectively. We followed the source code, you can see that the comparator is passed in to set this attribute to a treeemap defined in the treeset, and a property in the treemap sets this comparator:

 

Source code segment 7: treeset and treemap Constructor

public TreeSet(Comparator<? super E> comparator) {this(new TreeMap<E,Object>(comparator));}TreeSet(NavigableMap<E,Object> m) {    this.m = m;}public TreeMap(Comparator<? super K> comparator) {        this.comparator = comparator;}

Of course, this comparator is not set to treemap when it is not passed in. Let's take a look at the add method of treemap:

 

Source code snippet 8: treeset # Add (E)

 

Public
Boolean
Add (E ){

Return
M. Put (E, present) =Null;

}

What is m? In fact, we can see from source code segment 7 that M is a treemap that begins to be instantiated, so we need to look at the PUT Method of treemap.

 

Code snippet 9: treemap # Put (K key, V value)

public V put(K key, V value) {        Entry<K,V> t = root;        if (t == null) {            root = new Entry<K,V>(key, value, null);            size = 1;            modCount++;            return null;        }        int cmp;        Entry<K,V> parent;        // split comparator and comparable paths        Comparator<? super K> cpr = comparator;        if (cpr != null) {            do {                parent = t;                cmp = cpr.compare(key, t.key);                if (cmp < 0)                    t = t.left;                else if (cmp > 0)                    t = t.right;                else                    return t.setValue(value);            } while (t != null);        }        else {            if (key == null)                throw new NullPointerException();            Comparable<? super K> k = (Comparable<? super K>) key;            do {                parent = t;                cmp = k.compareTo(t.key);                if (cmp < 0)                    t = t.left;                else if (cmp > 0)                    t = t.right;                else                    return t.setValue(value);            } while (t != null);        }        Entry<K,V> e = new Entry<K,V>(key, value, parent);        if (cmp < 0)            parent.left = e;        else            parent.right = e;        fixAfterInsertion(e);        size++;        modCount++;        return null;    }

It is determined whether there is a comparator to write different locations in different ways, and there is no overload method, so there is not necessarily anything to do in implementation, just to ensure that the Code is readable, everything serves it. Otherwise, too many designs are over-designed. Of course, it doesn't mean that code design is not important, but these needs to be appropriate; in addition, other methods are sorted in the treeset. Here we just use the add method as an example.

I believe you have some knowledge about Java sorting. Maybe this article is a bunch of nonsense. Because this article is not about sorting algorithms, we just tell you how Java sorts data, in most cases, you do not need to write your own sorting algorithms to complete sorting, which leads to unnecessary bugs, and the efficiency may not necessarily be the same as that provided by Java.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.