一. 认识 Comparator 接口
直入主题,实现 Comparator 接口,重写 compare 方法,对 List 集合进行排序。
先来认识一下Comparator接口
- compare(a,b):根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
- equals(obj):仅当指定的对象也是一个 Comparator,并且强行实施与此 Comparator 相同的排序时才返回 true。
- Collections.sort(list, new PriceComparator()):静态方法,第二个参数对象返回一个 int 类型的值,相当于一个标志,告诉 sort 方法按什么顺序来对 list 进行排序。
二. 简单教程
2.1. 创建工具类
public class SortList<E> {
/**
* 对list进行排序
* @param list 集合
* @param method 排序字段的方法名
* @param sort 排序标志(正序[asc],倒序[desc])
*/
public void Sort(List<E> list, final String method, final String sort) {
Collections.sort(list, new Comparator<E>() {
@Override
public int compare(Object a, Object b) {
int ret = 0;
try {
Method m1 = ((E) a).getClass().getMethod(method, null);
Method m2 = ((E) b).getClass().getMethod(method, null);
Object va = m1.invoke(((E) a), null);
Object vb = m2.invoke(((E) b), null);
// 默认正序,若是倒序,交换va与vb的值
if (sort != null && "desc".equals(sort))
va = vb + ((vb = va) == "" ? "" : "");
ret = va.toString().compareTo(vb.toString());
} catch (NoSuchMethodException ne) {
System.out.println(ne);
} catch (IllegalAccessException ie) {
System.out.println(ie);
} catch (InvocationTargetException it) {
System.out.println(it);
}
return ret;
}
});
}
}
2.2. 测试User实体类
public class User {
// 用户编号
private Integer userId;
// 用户姓名
private String userName;
public User(){
};
public User(Integer userId, String userName){
this.userId = userId;
this.userName = userName;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
2.3. 测试方法
public static void main(String[] args) {
List<User> userList = new ArrayList<User>();
User user1 = new User(1, "阿里巴巴");
userList.add(user1);
User user2 = new User(102, "阿里妈妈");
userList.add(user2);
User user3 = new User(28, "阿里姑姑");
userList.add(user3);
// 打印排序前的数据
System.out.println(JSON.toJSONString(userList, SerializerFeature.WriteMapNullValue));
// 开始以userName倒序排序
SortList<User> sortList = new SortList<User>();
// 注意:第二个参数getUserName为User对象的字段userName的get方法
sortList.Sort(userList, "getUserName", "desc");
// 打印排序后的数据
System.out.println(JSON.toJSONString(userList, SerializerFeature.WriteMapNullValue));
}
三. 排序工具类优化
如果用字段 userId 测试过的朋友会发现,排序后顺序直接按照最高位数字进行排序了,不符合实际需求。后来收集资料发现,compareTo() 方法用于将 Number 对象与方法的参数进行比较。可用于比较 Byte, Double, Integer, Float, Long 或 Short 类型。
因此我们先判断排序字段的类型再转化,代码如下:
if(UseTool.isNumber(va) && UseTool.isNumber(vb)){
// 数字类型
ret = UseTool.toNumber(va).compareTo(UseTool.toNumber(vb));
}else if(UseTool.isTime(va) && UseTool.isTime(vb)){
// 时间类型
ret = UseTool.toTime(va).compareTo(UseTool.toTime(vb));
}else{
// 其他类型
ret = UseTool.toStr(va).compareTo(UseTool.toStr(vb));
}
最后附上以上用到的方法:
public class UseTool {
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String H_M_S = "HH:mm:ss";
public static final String SECOND = "SECOND";
/**
* 判断是否为空
*/
public static boolean isEmpty(Object obj) {
return (obj == null || "".equals(obj.toString()) || "null".equals(obj.toString().trim())
|| "".equals(obj.toString().trim()) || "undefined".equals(obj.toString()));
}
/**
* 判断是否是数字(包括负数,浮点数)
*/
public static boolean isNumber(Object obj) {
if (UseTool.isEmpty(obj)) return false;
obj = obj.toString().trim();
Pattern pattern = Pattern.compile("-?[0-9]+.*[0-9]*");
return pattern.matcher(obj.toString()).matches();
}
/**
* 转换为数字(包括负数,浮点数)
*/
public static double toNumber(Object obj) {
double result = 0.0;
if(UseTool.isNumber(obj))
result = Double.valueOf(obj);
return result;
}
/**
* 判断是否为时间类型
* @return
*/
public static boolean isTime(Object obj) {
if (UseTool.isEmpty(obj)) return false;
String datevalue = UseTool.toStr(obj).replaceAll("/", "-");
String format = UseTool.YYYY_MM_DD;
if(datevalue.indexOf(":")>=0 && datevalue.indexOf("-")>=0){
format = UseTool.YYYY_MM_DD_HH_MM_SS;
}else if(datevalue.indexOf(":")>=0){
format = UseTool.H_M_S;
}
SimpleDateFormat fmt = new SimpleDateFormat(format);
try {
Date dd = fmt.parse(datevalue);
if (datevalue.equals(fmt.format(dd)))
return true;
return false;
} catch (Exception e) {
return false;
}
}
/**
* 转换为时间类型
*/
public static Date toTime(Object obj) {
if (UseTool.isEmpty(obj)) return null;
String datevalue = UseTool.toStr(obj).replaceAll("/", "-");
String format = UseTool.YYYY_MM_DD;
if(datevalue.indexOf(":")>=0 && datevalue.indexOf("-")>=0){
format = UseTool.YYYY_MM_DD_HH_MM_SS;
}else if(datevalue.indexOf(":")>=0){
format = UseTool.H_M_S;
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
try {
return sdf.parse(datevalue);
} catch (Exception e) {
return null;
}
}
/**
* 转换为字符串
*/
public static String toStr(Object str) {
return isEmpty(str) ? "" : str.toString().trim();
}
}
赠人玫瑰手留余香,若对您有帮助,来
点个赞
呗!