1.列表排序应用
在做java开发时,通常需要排序列表,通常实现的方法是针对一个实体的某个字段排序,本文将用反射机制实现对实体的任何字段排序。
2.通用比较器的实现
ComparatorFactory:创建比较器的类
package com.sangbill.advanced.order;
import java.util.Comparator;
public class ComparatorFactory<T> {
public Comparator<? super T> createComparator(String propertyName, String order) {
return new TComparator(propertyName, order);
}
public class TComparator implements Comparator<T> {
private String propertyName;
private String order;
public TComparator(String propertyName, String order) {
this.propertyName = propertyName;
this.order = order;
}
@Override
public int compare(T o1, T o2) {
int result = 0;
try {
result = LangUtils.TCompareTo(RefUtils.invokeGetterMethod(o1, propertyName).toString(),
RefUtils.invokeGetterMethod(o2, propertyName).toString(),
o1.getClass().getDeclaredField(propertyName).getType());
} catch (Exception e) {
e.printStackTrace();
}
result = "asc".equals(order) ? result : -result;
return result;
}
}
}
LangUtils:实现字段比较的类
package com.sangbill.advanced.order;
import java.io.UnsupportedEncodingException;
public class LangUtils {
/**
* 对于字符串,中文按拼音顺序
* @param s1
* @param s2
* @return
* @throws UnsupportedEncodingException
*/
public static int stringCompareTo(String s1, String s2) throws UnsupportedEncodingException {
String str1 = new String(s1.getBytes("GB2312"), "ISO-8859-1");
String str2 = new String(s2.getBytes("GB2312"), "ISO-8859-1");
return str1.compareTo(str2);
}
/**
* 对于数字的比较,统一成double比较
* @param d1
* @param d2
* @return
*/
public static int numCompareTo(double d1, double d2) {
double d = d1 - d2;
if(d>0)return 1;
else if(d<0)return -1;
else return 0;
}
/**
* 对两个long型的比较
* @param long1
* @param long2
* @return
*/
public static int longCompareTo(Long long1, Long long2) {
if(long1>long2)return 1;
else if(long1<long2)return -1;
else return 0;
}
/**
* 对两个布尔值比较
* @param boolean1
* @param boolean2
* @return
*/
private static int booleanCompareTo(boolean boolean1,boolean boolean2) {
int t1 = (boolean1)?1:0;
int t2 = (boolean2)?1:0;
return t1-t2;
}
/**
* 根据值和类型返回笔记哦啊结果
* @param e1
* @param e2
* @param fieldType
* @return
* @throws UnsupportedEncodingException
*/
public static int TCompareTo(String e1, String e2, Class<?> fieldType) throws UnsupportedEncodingException {
int result = 0;
if(String.class.equals(fieldType)){
result = stringCompareTo(e1, e2);
}else if(Integer.class.equals(fieldType)){
result = Integer.parseInt(e1)-Integer.parseInt(e2);
}else if(Long.class.equals(fieldType)){
result = longCompareTo(Long.valueOf(e1),Long.valueOf(e2));
}else if(Float.class.equals(fieldType)){
result = numCompareTo(Float.parseFloat(e1), Float.parseFloat(e2));
}else if(Double.class.equals(fieldType)){
result = numCompareTo(Double.parseDouble(e1), Double.parseDouble(e2));
}else if(Boolean.class.equals(fieldType)){
result = booleanCompareTo(Boolean.parseBoolean(e1),Boolean.parseBoolean(e2));
}
return result;
}
}
RefUtils:反射类
package com.sangbill.advanced.order;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.sun.xml.internal.ws.util.StringUtils;
public abstract class RefUtils {
/**
* 调用Getter方法.
* @throws Exception
*/
public static Object invokeGetterMethod(Object obj, String propertyName) throws Exception {
String getterMethodName = "get" + StringUtils.capitalize(propertyName);
return invokeMethod(obj, getterMethodName, new Class[] {}, new Object[] {});
}
public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
final Object[] args) throws Exception {
Method method = getAccessibleMethod(obj, methodName, parameterTypes);
if (method == null) {
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
}
try {
return method.invoke(obj, args);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
|| e instanceof NoSuchMethodException) {
return new IllegalArgumentException("Reflection Exception.", e);
} else if (e instanceof InvocationTargetException) {
return new RuntimeException("Reflection Exception.", ((InvocationTargetException) e).getTargetException());
} else if (e instanceof RuntimeException) {
return (RuntimeException) e;
}
return new RuntimeException("Unexpected Checked Exception.", e);
}
public static Method getAccessibleMethod(final Object obj, final String methodName,
final Class<?>... parameterTypes) {
//Assert.notNull(obj, "object不能为空");
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
Method method = superClass.getDeclaredMethod(methodName, parameterTypes);
method.setAccessible(true);
return method;
} catch (NoSuchMethodException e) {//NOSONAR
// Method不在当前类定义,继续向上转型
}
}
return null;
}
}
3.排序测试
Test:测试类
package com.sangbill.advanced.order;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class Test {
public static void main(String[] args) throws SecurityException, NoSuchMethodException {
int size = 5;
String[] properties = {"Id","age","count","point","isMember","name","passwd"};
String order = "asc";
ComparatorFactory<User> factory = new ComparatorFactory<User>();
List<User> userList = getUserList(size);
print(null,userList,null);
/*for (int i = 0; i < properties.length; i++) {
Collections.sort(userList,factory.createComparator(properties[i], order));
print(properties[i],userList,order);
} */
Collections.sort(userList,factory.createComparator(properties[1], order));
print(null,userList,null);
Collections.sort(userList,factory.createComparator(properties[2], order));
print(null,userList,null);
/*SortByMethod<User> sort = new SortByMethod<User>();
sort.sortByMethod(userList, "getName", false);
print(null,userList,null);
sort.sortByMethod(userList, "getPasswd", false);*/
}
private static void print(String properties, List<User> userList,String order) {
System.out.println("order by "+properties+" "+order);
for (User user : userList) {
System.out.println(String.format("Id:%-20d ,age:%-2d, count:%-5f, point:%-5f, isMenber:%-5b, name:%-10s, passwd:%-10s",
user.getId(),user.getAge(),user.getCount(),user.getPoint(),user.getIsMember(),user.getName(),user.getPasswd()));
}
System.out.println("\n\n");
}
/**
* get random userList
* @param size
* @return
*/
private static List<User> getUserList(int size) {
List<User> userList = new ArrayList<User>();
for (int i = 0; i < size; i++) {
User u = getUser();
userList.add(u);
}
return userList;
}
/**
* get random user
* @return
*/
private static User getUser() {
User u = new User();
Random r = new Random();
boolean[] results = {true,false};
u.setId(r.nextLong());
u.setAge(r.nextInt(100));
u.setCount(r.nextFloat());
u.setPoint(r.nextDouble());
u.setMember(results[r.nextInt(2)]);
u.setName(getString());
u.setPasswd(getString());
return u;
}
/**
* get random String
* @return
*/
private static String getString(){
String s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random r = new Random();
int length = r.nextInt(10)+1;
int sLength = s.length();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
sb.append(s.charAt(r.nextInt(sLength)));
}
return sb.toString();
}
}
User:实体类
package com.sangbill.advanced.order;
public class User {
private Long Id;
private Integer age;
private Float count;
private Double point;
private Boolean isMember;
private String name;
private String passwd;
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getCount() {
return count;
}
public void setCount(float count) {
this.count = count;
}
public double getPoint() {
return point;
}
public void setPoint(double point) {
this.point = point;
}
public boolean getIsMember() {
return isMember;
}
public void setMember(boolean isMember) {
this.isMember = isMember;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
}