Java中Comparable和Comparator的使用方法
内置引用类型的比较
Comparable用法
这些类会继承Comparable接口,实现compareTo方法,通过该方法来实现对象之间比较。例如String:
String str="abc"; //如果其中一个是例外一个起始开始的子串,返回长度之差
String str2 ="abcd123"; //否则返回第一个不相等的unicode码之差
System.out.println(str.compareTo(str2));
str ="abc";
str2 ="aad";
System.out.println(str.compareTo(str2));
String内部继承Comparable接口,实现compareTo方法:
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;
}
可用作引用类型集合的排序,封装一排序工具类Utils
public class Utils {
/**
* 容器排序 (使用泛型方法)
*/
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;
}
}
}
}
Comparator用法
我们还可以额外创建一个实现了Comparator接口的比较类来对集合进行排序,Comparator独立与实体类,便于应对各种排序规则。例如:
/**
* 排序规则的业务类
* @author Administrator
*
*/
public class StrComparator 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);
}
}
封装排序工具类:
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;
}
}
}
}
使用方法:
list =new ArrayList<String>();
list.add("a");
list.add("abcd");
list.add("abc");
list.add("def");
Utils.sort(list,new StrComparator());
System.out.println(list);
使用Collections对容器的比较
//Comparator
List<String> list =new ArrayList<String>();
list.add("a");
list.add("abcd");
list.add("abc");
list.add("def");
Collections.sort(list,new StrComparator());
System.out.println(list);
//使用String默认排序
list =new ArrayList<String>();
list.add("a");
list.add("abcd");
list.add("abc");
list.add("def");
Collections.sort(list);
System.out.println(list);
自定义数据排序
Comparable
用Comparable方式实现新闻条目排序,直接上代码:
public class News implements java.lang.Comparable<News>{
//标题
private String title;
//点击量
private int hits;
//时间
private Date publishTime;
public News() {
}
public News(String title, int hits, Date pubTime) {
super();
this.title = title;
this.hits = hits;
this.publishTime = 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 publishTime;
}
public void setPubTime(Date pubTime) {
this.publishTime = pubTime;
}
//首先按时间降序 +再按点击量升序+再按标题降序
@Override
public int compareTo(News o) {
int result =0;
//时间降序
result =this.publishTime.compareTo(o.publishTime);
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.publishTime));
sb.append(",点击量:").append(this.hits).append("\n");
return sb.toString();
}
}
实现排序
List<News> news=new ArrayList<News>();
news.add(new News("国产第十艘航母下水了",15000,new Date(System.currentTimeMillis()-1000*60*60)));
news.add(new News("乐天集团倒闭了",16000,new Date()));
news.add(new News("中国统一台湾",60000,new Date(System.currentTimeMillis()-1000*60*60)));
System.out.println("排序前:"+news);
//排序
//Collections.sort(news);
Utils.sort(news);
System.out.println("排序后"+news);
Comparator
实体类
public class Goods {
//商品名称
private String name;
//价格
private double price;
//销量
private int salesNum;
public Goods() {
}
public Goods(String name, double price, int salesNum) {
super();
this.name = name;
this.price = price;
this.salesNum = salesNum;
}
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 getSalesNum() {
return salesNum;
}
public void setSalesNum(int salesNum) {
this.salesNum = salesNum;
}
@Override
public String toString() {
return "商品名称:"+name+",销量"+this.salesNum+",价格:"+this.price+"\n";
}
}
实现Comparator接口,按销量排序的业务类 (降序)
public class GoodsSalesNumCompare implements java.util.Comparator<Goods> {
@Override
public int compare(Goods good1, Goods good2) {
return -(good1.getSalesNum()-good2.getSalesNum());
}
}
实现Comparator接口,按价格排序的业务类 (降序)
public class GoodsPriceCompare implements java.util.Comparator<Goods> {
@Override
public int compare(Goods good1, Goods good2) {
return -(good1.getPrice()-good2.getPrice()>0?1:(good1.getPrice()==good2.getPrice()?0:-1));
}
}
实现排序
List<Goods> list =new ArrayList<Goods>();
list.add(new Goods("iphone7plus",6300,2000));
list.add(new Goods("华为P10",3600,12000));
list.add(new Goods("小米MIX",3500,10000));
System.out.println("排序前:"+list);
Collections.sort(list,new GoodsSalesNumCompare());//商品按销售数量降序排序
//Collections.sort(list,new GoodsPriceCompare());//商品按价格降序排序
System.out.println("排序后:"+list);