当我们获得一个List后,如果希望它是按容器中,元素的某种属性排序的话,我们是可以通过
Collections.sort(myList, new my比较器())进行排序的。
但问题是,不同的属性要写不同的比较器,不同的类也要写比较器。
如果不希望重复劳动,就需要一个通用的比较器,所以写了以下代码。
我自己命名的:基本类型单一通用比较器 是指
(1)基本类型:元素的属性必须是:boolean,byte,char,int,long,float,double及他们的包装类 + String,Date,BigDecimal这几种类型
(2)所谓的单一(Single)是指:只比较类中的某一属性(不像SQL 的odrder by,后面可以跟n个,以后会扩展)
(3)通用(Universal)是指:任何类都可以用(希望如此)
废话少说,代码如下:
public final class BasicDataSingleUniversalComparator implements Comparator<Object> {
private Class<?> c; //要比较的类
private String fieldName; //根据类的哪个属性比较
private Field field;
private String filedTypeName; //属性类型名称
//private Class<Object> attributeClass; //要比较的类的属性的类型
private boolean isAsc; //比较结果是升序 or倒序, true:根据类属性自然比较结果的升序排列, false:根据类属性自然比较结果的倒序排列
private int asc;
private final static Map<String, String> compareMethods;
static {
compareMethods = new HashMap<String, String>();
// * boolean,byte,char,int,long,float,double及他们的包装类 + String,Date这几种类型
compareMethods.put("boolean", "compareBoolean");
compareMethods.put("byte", "compareByte");
compareMethods.put("char", "compareCharacter");
compareMethods.put("character", "compareCharacter");
compareMethods.put("int", "compareInteger");
compareMethods.put("integer", "compareInteger");
compareMethods.put("long", "compareLong");
compareMethods.put("float", "compareFloat");
compareMethods.put("double", "compareDouble");
compareMethods.put("string", "compareString");
compareMethods.put("date", "compareDate");
compareMethods.put("bigdecimal", "compareBigDecimal");
}
//public SingleAttributeComparator(){}
/**
* 构造函数
* @param c 要比较的类
* @param fieldName 类的某一属性名称
* @param isAsc 是根据此属性升序排列 or倒序排列 :true为升序,false为倒序
*/
public BasicDataSingleUniversalComparator(Class<?> c, String fieldName, boolean isAsc)
throws Exception {
this.c = c;
this.fieldName = fieldName;
field = this.c.getDeclaredField(this.fieldName);
filedTypeName = field.getType().getSimpleName();
this.isAsc = isAsc;
if(this.isAsc) {
asc = 1;
} else {
asc = -1;
}
}
@Override
public int compare(Object o1, Object o2) {
int result = 0;
// String fieldType = field.getType().getSimpleName();
try {
field.setAccessible(true); //破坏了private,另外一种方案是:调用属性的get方法,但必须保证要有规范的get方法
Object value1 = field.get(o1);
Object value2 = field.get(o2);
result = compareBasicData(value1, value2);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 认为null是最小的
* @param value1
* @param value2
* @return
* @throws NoSuchMethodException
* @throws SecurityException
*/
private int compareBasicData(Object value1, Object value2) throws Exception {
int result = 0;
if((value1 == null && value2 == null)) {
result = 0;
} else if(value1 == null) {
result = -1*asc; //null是最小的,返回1*asc,如果是升序,则1*asc=1,否则1*asc=-1
} else if(value2 == null) {
result = 1*asc;
} else if(value1.equals(value2)) {
result = 0;
} else {
Method method = this.getClass().getDeclaredMethod(compareMethods.get(filedTypeName.toLowerCase()), Object.class, Object.class);
result = (Integer)method.invoke(this, value1, value2);
}
return result*asc;
}
@SuppressWarnings("unused")
private int compareBoolean(final Object value1, final Object value2) {
Boolean v1 = (Boolean)value1;
Boolean v2 = (Boolean)value2;
return v1.compareTo(v2);
}
@SuppressWarnings("unused")
private int compareByte(final Object value1, final Object value2) {
Byte v1 = (Byte)value1;
Byte v2 = (Byte)value2;
return v1.compareTo(v2);
}
@SuppressWarnings("unused")
private int compareCharacter(final Object value1, final Object value2) {
Character v1 = (Character)value1;
Character v2 = (Character)value2;
return v1.compareTo(v2);
}
@SuppressWarnings("unused")
private int compareInteger(final Object value1, final Object value2) {
Integer v1 = (Integer)value1;
Integer v2 = (Integer)value2;
return v1.compareTo(v2);
}
@SuppressWarnings("unused")
private int compareLong(final Object value1, final Object value2) {
Long v1 = (Long)value1;
Long v2 = (Long)value2;
return v1.compareTo(v2);
}
@SuppressWarnings("unused")
private int compareFloat(final Object value1, final Object value2) {
Float v1 = (Float)value1;
Float v2 = (Float)value2;
return v1.compareTo(v2);
}
@SuppressWarnings("unused")
private int compareDouble(final Object value1, final Object value2) {
Double v1 = (Double)value1;
Double v2 = (Double)value2;
return v1.compareTo(v2);
}
@SuppressWarnings("unused")
private int compareDate(final Object value1, final Object value2) {
Date v1 = (Date)value1;
Date v2 = (Date)value2;
return v1.compareTo(v2);
}
@SuppressWarnings("unused")
private int compareString(final Object value1, final Object value2) {
String v1 = (String)value1;
String v2 = (String)value2;
return v1.compareTo(v2);
}
@SuppressWarnings("unused")
private int compareBigDecimal(final Object value1, final Object value2) {
BigDecimal v1 = (BigDecimal)value1;
BigDecimal v2 = (BigDecimal)value2;
return v1.compareTo(v2);
}
}
使用方法如下:
例如我有一个Airport 机场类,里面有一个属性airportCode(机场三字码),
现在myList存放的是Airport元素列表,希望根据airportCode倒序排列(升序true,倒序false),那么
Collections.sort(myList, new BasicDataSingleUniversalComparator (Airport.class, "airportCode", false));
就搞定了。