实例3(将上面的UserDO使用一个叫UserComparableDO在类的基础上进行排序)
首先将UserDO重新编写为UserComparableDO:
import java.text.Collator;
import java.util.Comparator;
public class UserComparableDO extends UserDO implements Comparable {
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")
@Override
public int compareTo(UserDO userDO) {
return CHINA_COMPARE.compare(this.getName(), userDO.getName());
}
}
当然这段代码里面直接在里面定义一个Comparator是不正确的,一般这个东西是被抽象到系统某些公共的Commons组件里面的,其次,如果原本没有UserDO类,相应的属性写一次即可,我这里原本有UserDO所有直接集成,减少很多代码。
此时就不需要自己再去写一个Comparator了,就可以直接排序了,下面是我们的测试程序:
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() {
SortedSetuserSet = new TreeSet();
userSet.add(new UserComparableDO("张三" , "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() {
Listlist = Arrays.asList(
new UserComparableDO("张三" , "aaazhangsan@ddd.com"),
new UserComparableDO("李四" , "ddlisi@dsfds.com"),
new UserComparableDO("王五" , "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("张三" , "aaazhangsan@ddd.com"),
new UserComparableDO("李四" , "ddlisi@dsfds.com"),
new UserComparableDO("王五" , "ddwangwu@fsadfads.com")
};
Arrays.sort(userDOArray);
for(UserComparableDO userDO : userDOArray) {
System.out.println(userDO.getName());
}
}
}
可以看到本次排序中没有再使用自定义的Comparator作为参数,另外TreeSet的入口参数也没有再传入这些参数。
结果知道了,我们简单看看相关的源码来证实这个说法,我们首先来看Collections.sort方法:
源码片段1:Collections.sort(List list)
public static > void sort(List list) {
Object[] a = list.toArray();
Arrays.sort(a);
ListIterator i = list.listIterator();
for (int j=0; j
i.next();
i.set((T)a[j]);
}
}
此时直接调用了Arrays.sort(a)来排序后,将数组的数据写回到list,另外根据方法的定义,泛型T要求传入的类必须是Comparable类的子类或实现类,所以要调用Collections.sort(list)这个方法,传入的list中包含的每行数据必须是implements Comparable这个接口的,否则编译时就会报错。
再看重载方法,传入自定义的Comparator
源码片段2:Collections.sort(List list, Comparator super T> c)
public static void sort(List list, Comparator super T> c) {
Object[] a = list.toArray();
Arrays.sort(a, (Comparator)c);
ListIterator i = list.listIterator();
for (int j=0; j
i.next();
i.set(a[j]);
}
}
也是和第一个方法类似,就是调用了Arrays.sort相应的重载方法,看来都是在Arrays里面是实现的,那么就进一步向下看:
源码片段3:Arrays.sort(T[]t):
public static void sort(Object[] a) {
Object[] aux = (Object[])a.clone();
mergeSort(aux, a, 0, a.length, 0);
}
看来代码片段交给了mergeSort来处理,而对数组做了一次克隆,作为排序的基础数据,而原来的数组作为排序的目标,mergeSort的代码片段应该是核心部分,我们先放在这里,先看下sort的另一个重载方法,另外需要注意,这里并没有像Collections.sort(Listlist)那样在编译时检查类型,也就是在使用这个方法的时候,数组里面的每行并没有implements Comparable也会不会出错,只是在运行时会报错而已,在下面的源码中会有说明。
源码片段4 : Arrays.sort(T[]t, Comparator super T> c)
public static 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也进行了重载,也就是当传入了自定义的Comparator和不传入自定义的Comparator是调用不同的方法来实现的,然后我们来看下两个方法的实现。
32/3<123>