【通用版】Java List根据对象某一元素重新排序

一. 认识 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();
	}
	
}

赠人玫瑰手留余香,若对您有帮助,来 点个赞呗!

猜你喜欢

转载自blog.csdn.net/ii950606/article/details/106708204
今日推荐