今天,简单讲讲android的如何使用
Comparator比较对象的大小。
记得之前也讲过比较对象的大小,也是使用Comparator,但是但是讲的比较浅,而且有些细节没有弄好。最近再次需要使用Comparator比较对象大小,所以自己在网上查找了资料,解决了问题。这里记录一下。
Java中实现对象的比较:Comparable接口和Comparator接口
在实际应用中,我们往往有需要比较两个自定义对象大小的地方。而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的。所以Java中要比较对象的大小或者要对对象的集合进行排序,需要通过比较这些对象的某些属性的大小来确定它们之间的大小关系。
一般,Java中通过接口实现两个对象的比较,比较常用就是Comparable接口和Comparator接口。首先类要实现接口,并且使用泛型规定要进行比较的对象所属的类,然后类实现了接口后,还需要实现接口定义的比较方法(compareTo方法或者compare方法),在这些方法中传入需要比较大小的另一个对象,通过选定的成员变量与之比较,如果大于则返回1,小于返回-1,相等返回0。
一、Comparable接口
1.什么是Comparable接口
此接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序 ,类的 compareTo方法被称为它的自然比较方法 。实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort )进行自动排序。实现此接口的对象可以用作有序映射表中的键或有序集合中的元素,无需指定比较器。
2.实现什么方法
int compareTo(T o)
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
参数: o - 要比较的对象。
返回:负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
抛出:ClassCastException - 如果指定对象的类型不允许它与此对象进行比较。
3.实例
package com.mxl.algorithlm;
import java.util.Date;
/**
* 因为要实现对ConsumInfo对象的排序,所以在ConsunInfo类中要实现Comparable接口,也就是要实现compareTo()方法
* 具体的比较参照:依次按照price、uid进行倒序排序
* @author breeze
*
*/
public class ConsumInfo implements Comparable<ConsumInfo> {
private int uid;
private String name;
private double price;
private Date datetime;
public ConsumInfo() {
// TODO Auto-generated constructor stub
}
public ConsumInfo(int uid,String name,double price,Date datetime){
this.uid = uid;
this.name = name;
this.price = price;
this.datetime = datetime;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
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 Date getDatetime() {
return datetime;
}
public void setDatetime(Date datetime) {
this.datetime = datetime;
}
@Override
public String toString() {
return "ConsumInfo [uid=" + uid + ", name=" + name + ", price=" + price
+ ", datetime=" + datetime + "]";
}
/**
* 这里比较的是什么, Collections.sort方法实现的就是按照此比较的东西排列
* 顺序(从小到大):
* if(price < o.price){
return -1;
}
if(price > o.price){
return 1;
}
* 倒序(从大到小):
* if(price < o.price){
return 1;
}
if(price > o.price){
return -1;
}
*
*/
@Override
public int compareTo(ConsumInfo o) {
//首先比较price,如果price相同,则比较uid
if(price < o.price){
return -1;
}
if(price > o.price){
return 1;
}
if(price == o.price){
if(uid < o.uid){
return -1;
}
if(uid > o.uid){
return 1;
}
}
return 0;
}
}
//测试类
package com.mxl.algorithlm;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class ConsumInfoTest {
public static void main(String[] args) {
ConsumInfo consumInfo1 = new ConsumInfo(100, "consumInfo1", 400.0,new Date());
ConsumInfo consumInfo2 = new ConsumInfo(200, "consumInfo1", 200.0,new Date());
ConsumInfo consumInfo3 = new ConsumInfo(300, "consumInfo1", 100.0,new Date());
ConsumInfo consumInfo4 = new ConsumInfo(400, "consumInfo1", 700.0,new Date());
ConsumInfo consumInfo5 = new ConsumInfo(500, "consumInfo1", 800.0,new Date());
ConsumInfo consumInfo6 = new ConsumInfo(600, "consumInfo1", 300.0,new Date());
ConsumInfo consumInfo7 = new ConsumInfo(700, "consumInfo1", 900.0,new Date());
ConsumInfo consumInfo8 = new ConsumInfo(800, "consumInfo1", 400.0,new Date());
List<ConsumInfo> list = new ArrayList<ConsumInfo>();
list.add(consumInfo1);
list.add(consumInfo2);
list.add(consumInfo3);
list.add(consumInfo4);
list.add(consumInfo5);
list.add(consumInfo6);
list.add(consumInfo7);
list.add(consumInfo8);
System.out.println("排序前:");
//排序前
for(ConsumInfo consumInfo : list ){
System.out.println(consumInfo);
}
Collections.sort(list);//排序
System.out.println("排序后:");
//排序后
for(ConsumInfo consumInfo :list){
System.out.println(consumInfo);
}
}
}
这里,我说一下,其实就是让类实现Comparable接口,然后之前调用Collections.sort(list)进行排序。但是我使用这个Comparable接口是没有成功对对讲进行排序,不知道为什么,大家有兴趣可以试试。
二、Comparator接口
与上面的Comparable接口不同的是:
①、Comparator位于包java.util下,而Comparable位于包java.lang下。
②、Comparable接口将比较代码嵌入需要进行比较的类的自身代码中,而Comparator接口在一个独立的类中实现比较。
③、如果前期类的设计没有考虑到类的Compare问题而没有实现Comparable接口,后期可以通过Comparator接口来实现比较算法进行排序,并且为了使用不同的排序标准做准备,比如:升序、降序。
④、Comparable接口强制进行自然排序,而Comparator接口不强制进行自然排序,可以指定排序顺序。
使用实例:
package test;
import java.util.Comparator;
/**
* 具体的比较类(比较器),实现Comparator接口
* @author breeze
*
*/
public class ComparatorConsunInfo implements Comparator<ConsumInfo> {
/**
* 顺序(从小到大):
* if(price < o.price){
return -1;
}
if(price > o.price){
return 1;
}
* 倒序(从大到小):
* if(price < o.price){
return 1;
}
if(price > o.price){
return -1;
}
*/
@Override
public int compare(ConsumInfo o1, ConsumInfo o2) {
//首先比较price,如果price相同,则比较uid
if(o1.getPrice() > o2.getPrice()){
return 1;
}
if(o1.getPrice() < o2.getPrice()){
return -1;
}
if(o1.getPrice() == o2.getPrice()){
if(o1.getUid() > o2.getUid()){
return 1;
}
if(o1.getUid() < o2.getUid()){
return -1;
}
}
return 0;
}
}
/**
* 需要进行比较的类
* @author breeze
*
*/
public class ConsumInfo{
private int uid;
private String name;
private double price;
private Date datetime;
public ConsumInfo() {
// TODO Auto-generated constructor stub
}
public ConsumInfo(int uid,String name,double price,Date datetime){
this.uid = uid;
this.name = name;
this.price = price;
this.datetime = datetime;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
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 Date getDatetime() {
return datetime;
}
public void setDatetime(Date datetime) {
this.datetime = datetime;
}
@Override
public String toString() {
return "ConsumInfo [uid=" + uid + ", name=" + name + ", price=" + price
+ ", datetime=" + datetime + "]";
}
}
//测试类
public class ConsumInfoTest {
public static void main(String[] args) {
ConsumInfo consumInfo1 = new ConsumInfo(100, "consumInfo1", 400.0,new Date());
ConsumInfo consumInfo2 = new ConsumInfo(200, "consumInfo1", 200.0,new Date());
ConsumInfo consumInfo3 = new ConsumInfo(300, "consumInfo1", 100.0,new Date());
ConsumInfo consumInfo4 = new ConsumInfo(400, "consumInfo1", 700.0,new Date());
ConsumInfo consumInfo5 = new ConsumInfo(500, "consumInfo1", 800.0,new Date());
ConsumInfo consumInfo6 = new ConsumInfo(600, "consumInfo1", 300.0,new Date());
ConsumInfo consumInfo7 = new ConsumInfo(700, "consumInfo1", 900.0,new Date());
ConsumInfo consumInfo8 = new ConsumInfo(800, "consumInfo1", 400.0,new Date());
List<ConsumInfo> list = new ArrayList<ConsumInfo>();
list.add(consumInfo1);
list.add(consumInfo2);
list.add(consumInfo3);
list.add(consumInfo4);
list.add(consumInfo5);
list.add(consumInfo6);
list.add(consumInfo7);
list.add(consumInfo8);
System.out.println("排序前:");
//排序前
for(ConsumInfo consumInfo : list ){
System.out.println(consumInfo);
}
ComparatorConsunInfo comparatorConsunInfo = new ComparatorConsunInfo();//比较器
Collections.sort(list,comparatorConsunInfo);//排序
System.out.println("排序后:");
//排序后
for(ConsumInfo consumInfo :list){
System.out.println(consumInfo);
}
}
}
这里需要知道使用Comparator接口,一定需要处理对象>0,=0,和<0的情况,不能忽略对象相等的情况。
接下来再举一个例子:
假设现在有个如此的需求:需要对一个这样的雇员列表进行排序,排序规则如下:
1、首先级别最高的排在前面,
2、如果级别相等,那么按工资排序,工资高的排在前面,
3、如果工资相当则按入职年数排序,入职时间最长的排在前面。
雇员对象包含级别、工资和入职年份,代码如下:
package com.lyz.sort.bean;
import java.io.Serializable;
/**
* 雇员信息
* @author liuyazhuang
*
*/
public class Employee implements Serializable {
private static final long serialVersionUID = 4775629632953317597L;
/**
* ID
*/
public int id;
/**
* 级别
*/
public int level;
/**
* 工资
*/
public int salary;
/**
* 入职年数
*/
public int year;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public Employee(int id, int level, int salary, int year) {
this.id = id;
this.level = level;
this.salary = salary;
this.year = year;
}
}
二、实现Comparator接口
这里我们实现Java.util.Comparator接口,用于对雇员列表进行排序,代码如下:
package com.lyz.sort;
import java.util.Comparator;
import com.lyz.sort.bean.Employee;
/**
* 核心排序类
* @author liuyazhuang
*
*/
public class EmpComparator implements Comparator<Employee> {
@Override
public int compare(Employee employee1, Employee employee2) {
int cr = 0;
//按级别降序排列
int a = employee2.getLevel() - employee1.getLevel();
if (a != 0) {
cr = (a > 0) ? 3 : -1;
} else {
//按薪水降序排列
a = employee2.getSalary() - employee1.getSalary();
if (a != 0) {
cr = (a > 0) ? 2 : -2;
} else {
//按入职年数降序排列
a = employee2.getYear() - employee1.getYear();
if (a != 0) {
cr = (a > 0) ? 1 : -3;
}
}
}
return cr;
}
}
三、验证排序结果
下面用一个单元测试,来验证排序结果是否正确
package com.lyz.sort.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import com.lyz.sort.EmpComparator;
import com.lyz.sort.bean.Employee;
/**
* 测试排序类
*
* @author liuyazhuang
*
*/
public class SortTest {
@Test
public void sortTest() throws Exception {
List<Employee> employeeList = new ArrayList<Employee>() {
{
add(new Employee(1, 9, 10000, 10));
add(new Employee(2, 9, 12000, 7));
add(new Employee(3, 5, 10000, 12));
add(new Employee(4, 5, 10000, 6));
add(new Employee(5, 3, 5000, 3));
add(new Employee(6, 1, 2500, 1));
add(new Employee(7, 5, 8000, 10));
add(new Employee(8, 3, 8000, 2));
add(new Employee(9, 1, 3000, 5));
add(new Employee(10, 1, 2500, 4));
add(new Employee(11, 2, 2000, 4));
}
};
Collections.sort(employeeList, new EmpComparator());
System.out.println("ID\tLevel\tSalary\tYears");
System.out.println("=============================");
for (Employee employee : employeeList) {
System.out.printf("%d\t%d\t%d\t%d\n", employee.getId(), employee.getLevel(), employee.getSalary(),
employee.getYear());
}
System.out.println("=============================");
}
}
运行结果:
android Comparator的使用就讲完了。
就这么简单。