1 Comarable类:
基本数据类型比较 jvm已经定义好了
自定义Java类型的比较,需要把比较大小规则告诉jvm.
需要 实现 Comparable接口,并重写compareto方法。
这个接口的比较缺点:
s.compareTo(b) ---》 我和你去比较, 没有脱离实体类的比较器接口和方法
内置引用数据类型(常用)的比较 ,可以看源码,看到这些基本数据类型类都实现了Comparable接口,并重写compareto方法。
public static void main(String[] args) { Integer a ; //根据基本数据类型大小 Character ch; //根据Unicode编码顺序 String str="abc"; //如果其中一个是例外一个起始开始的子串,返回长度之差 String str2 ="abcd123"; //否则返回第一个不相等的unicode码之差 System.out.println(str.compareTo(str2)); str ="abc"; str2 ="aad"; System.out.println(str.compareTo(str2)); java.util.Date d ; //根据日期的长整形数比较 }
其中,String类型的比较:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { // 实现Comparable接口 实现这个方法, public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int k = 0; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; // 否则返回字符串长度只差 }
比如如下比较:
"010001001771339008001" ---> 变成char数组后 是从左向右来比较的
"010001001771339008"
"010001001771339007001"
字符串"010001001771339008001"和"010001001771339008"比较时, 先获取第二个字符串的长度作为最小长度,
此时在比较完第二个参数长度后跳出 while循环,继续向下走到 return len1 - len2; 因此得到 第一个字符串要比第二个字符串大
在比较
"010001001771339008" 和 "010001001771339007001" 时, 获取"010001001771339008" 的长度,然后
"010001001771339008" 变成 char[]时候 为 ['0','1','0','0','0','1','0','0','1','7','7','1','3','3','9','0','0','8']
在和"010001001771339007001"变成char数组的长度后为 ['0','1','0','0','0','1','0','0','1','7','7','1','3','3','9','0','0','7']比较时,从左向右比较,因此得到 010001001771339008 要比 010001001771339007001大的结果
2 Comparator 类的使用 : 感觉这个类就是为了扩展Comparable而产生的
Comparator类: 传递两个参数 来比较 (s,b)
独立于实体,脱离实体的比较器类,解耦,方便定制各种业务场景的排序规则。
public class StringComp implements java.util.Comparator<String>{ /** * 按长度比较大小 * 正数 > * 负数 < * 0 == */ @Override public int compare(String o1, String o2) { int len1 =o1.length(); int len2 =o2.length(); return -(len1-len2); } }
3 等同于 :java.util.Collections.sort(list)的自定义实现 比较代码
/** * 排序 * @author Administrator * */ public class Utils { /** * List的排序+比较器 * @param list * @param com */ public static <T> void sort(List<T> list,Comparator<T> com){ //第一步:转成数组 Object[] arr =list.toArray(); sort(arr,com); //第二步:改变容器中对应的值 for(int i=0;i<arr.length;i++){ list.set(i, (T)(arr[i])); } } /** * 数组的排序 (降序)+Comparator接口 * @param arr */ public static <T> void sort(Object[] arr,Comparator<T> com){ //从大到小排序 降序 boolean sorted= true; int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 sorted =true; //假定有序 for(int i=0;i<len-1-j;i++){ //次数 if(com.compare((T)arr[i], (T)arr[i+1])<0){ Object temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; sorted =false; //假定失败 } } if(sorted){ //减少趟数:上面这一趟比较下来,如果没有互换位置的,那么就终止下一趟的比较 break; } } } /** * 容器排序 (使用泛型方法) */ public static <T extends Comparable<T>> void sort(List<T> list){ //第一步:转成数组 Object[] arr =list.toArray(); sort(arr); //第二步:改变容器中对应的值 for(int i=0;i<arr.length;i++){ list.set(i, (T)(arr[i])); } } /** * 数组排序 (使用泛型方法) */ public static <T extends Comparable<T>> void sort(T[] arr){ //从大到小排序 降序 boolean sorted= true; int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 sorted =true; //假定有序 for(int i=0;i<len-1-j;i++){ //次数 if(((Comparable)arr[i]).compareTo(arr[i+1])<0){ T temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; sorted =false; //假定失败 } } if(sorted){ //减少趟数 break; } } } /** * 数组的排序 (降序) * @param arr */ public static void sort(Object[] arr){ //从大到小排序 降序 boolean sorted= true; int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 sorted =true; //假定有序 for(int i=0;i<len-1-j;i++){ //次数 if(((Comparable)arr[i]).compareTo(arr[i+1])<0){ Object temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; sorted =false; //假定失败 } } if(sorted){ //减少趟数 break; } } } }
2 业务类分别使用这两种方式排序 :
2.1 业务类内使用Comparable,耦合比较方法:
public class NewsItem implements java.lang.Comparable<NewsItem>{ //标题 private String title; //点击量 private int hits; //时间 private Date pubTime; public NewsItem() { } public NewsItem(String title, int hits, Date pubTime) { super(); this.title = title; this.hits = hits; this.pubTime = pubTime; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getHits() { return hits; } public void setHits(int hits) { this.hits = hits; } public Date getPubTime() { return pubTime; } public void setPubTime(Date pubTime) { this.pubTime = pubTime; } //时间降序 +点击量升序+标题降序 @Override public int compareTo(NewsItem o) { int result =0; //比较 时间 result =-this.pubTime.compareTo(o.pubTime); //降序, 默认是升序,这里期待是降序 因此加上 - if(0==result){ //时间相同 //点击量 result =this.hits-o.hits; //升序 if(0==result){ //点击量相同 //标题 result=-this.title.compareTo(o.title);//降序 } } return result; } @Override public String toString() { StringBuilder sb =new StringBuilder(); sb.append("标题:").append(this.title); sb.append(",时间:").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.pubTime)); sb.append(",点击量:").append(this.hits).append("\n"); return sb.toString(); } } 调用: public static void main(String[] args) { List<NewsItem> news=new ArrayList<NewsItem>(); news.add(new NewsItem("美国后怕了,逃跑了悲剧了",50,new Date(System.currentTimeMillis()-1000*60*60))); news.add(new NewsItem("中国登上钓鱼岛了,全国欢呼了",100,new Date())); news.add(new NewsItem("小日本终于听话了,泪流满面笑了",60,new Date(System.currentTimeMillis()-1000*60*60))); System.out.println("排序前:"+news); //排序 Collections.sort(news); //Utils.sort(news); System.out.println("排序后"+news); }
2.2 使用 Comparator类,业务类不需要耦合排序方法:
干净的业务类: public class Goods { //商品名称 private String name; //价格 private double price; //收藏量 private int fav; public Goods() { // TODO Auto-generated constructor stub } public Goods(String name, double price, int fav) { super(); this.name = name; this.price = price; this.fav = fav; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getFav() { return fav; } public void setFav(int fav) { this.fav = fav; } @Override public String toString() { return "商品名:"+name+",收藏量"+this.fav+",价格:"+this.price+"\n"; } } 按需定义的比较类1: * 按收藏量排序的业务类 (升序) * @author Administrator * */ public class GoodsFavComp implements java.util.Comparator<Goods> { @Override public int compare(Goods o1, Goods o2) { return o1.getFav()-o2.getFav(); } } 比较类2: * 按价格排序的业务类 (降序) * @author Administrator * */ public class GoodsPriceComp implements java.util.Comparator<Goods> { @Override public int compare(Goods o1, Goods o2) { return -(o1.getPrice()-o2.getPrice()>0?1:(o1.getPrice()==o2.getPrice()?0:-1)); } } 调用: public static void main(String[] args) { List<Goods> list =new ArrayList<Goods>(); list.add(new Goods("鹦鹉视频",100,2000)); list.add(new Goods("小厨视频",50,2000)); list.add(new Goods("新东方视频",1000,1000)); System.out.println("排序前:"+list); // Collections.sort(list,new GoodsPriceComp()); // 按价格排序的业务类 Collections.sort(list,new GoodsFavComp()); // 按收藏量排序的业务类 (升序) System.out.println("排序后:"+list); }