Compareable和Comparator类和业务类分别使用这两个比较类排序

 

 

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

 

 

猜你喜欢

转载自chengjianxiaoxue.iteye.com/blog/2398723
今日推荐