List集合根據指定屬性進行排序

主要通過反射拿到對象的屬性,然後重寫sort方法,比較屬性值。代碼如下:

package cn.sinobest.sdg.util;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @description 集合工具類
 * @author: dengweiping
 * @time: 2020/6/1 14:49
 */
public class ListUtil {

    /**
     * 根據指定屬性升序排序
     *
     * @param list         集合
     * @param propertyName 屬性名
     * @param <T>
     * @return
     */
    public static <T> List<T> sortAsc(List<T> list, String propertyName) {
        return sort(list, propertyName, "asc", false);
    }

    /**
     * 根據指定屬性升序排序,忽略大小寫
     *
     * @param list         集合
     * @param propertyName 屬性名
     * @param <T>
     * @return
     */
    public static <T> List<T> sortAscIgnoreCase(List<T> list, String propertyName) {
        return sort(list, propertyName, "asc", true);
    }

    /**
     * 根據指定屬性降序排序
     *
     * @param list         集合
     * @param propertyName 屬性名
     * @param <T>
     * @return
     */
    public static <T> List<T> sortDesc(List<T> list, String propertyName) {
        return sort(list, propertyName, "desc", false);
    }

    /**
     * 根據指定屬性降序排序,忽略大小寫
     *
     * @param list         集合
     * @param propertyName 屬性名
     * @param <T>
     * @return
     */
    public static <T> List<T> sortDescIgnoreCase(List<T> list, String propertyName) {
        return sort(list, propertyName, "desc", true);
    }

    /**
     * 根據指定方式排序
     *
     * @param list         集合
     * @param propertyName 屬性名
     * @param sortType     排序方式 asc:升序 desc:降序
     * @param <T>
     * @return
     */
    private static <T> List<T> sort(List<T> list, String propertyName, String sortType, boolean ignoreCase) {
        Collections.sort(list, (Comparator<Object>) (o1, o2) -> {
            try {
                Field field1 = o1.getClass().getDeclaredField(propertyName);
                Field field2 = o2.getClass().getDeclaredField(propertyName);
                //打開私有訪問
                field1.setAccessible(true);
                field2.setAccessible(true);
                String type = field1.getType().getName();
                Object obj1 = field1.get(o1);
                Object obj2 = field2.get(o2);
                if (obj1 == null) {
                    return -1;
                } else if (obj2 == null) {
                    return 1;
                }
                boolean isAsc = "asc".equals(sortType);
                switch (type) {
                    case "int":
                        return isAsc ? ((int) obj1 - (int) obj2) : ((int) obj2 - (int) obj1);
                    case "long":
                    case "java.lang.Long":
                        return (long) obj1 > (long) obj2 ? (isAsc ? 1 : -1) : (isAsc ? -1 : 1);
                    case "double":
                    case "java.lang.Double":
                        return (double) obj1 > (double) obj2 ? (isAsc ? 1 : -1) : (isAsc ? -1 : 1);
                    case "float":
                    case "java.lang.Float":
                        return (float) obj1 > (float) obj2 ? (isAsc ? 1 : -1) : (isAsc ? -1 : 1);
                    case "java.lang.String":
                        //循環比較次數以字符串短的爲準
                        int length = obj1.toString().length() < obj2.toString().length() ? obj1.toString().length() : obj2.toString().length();
                        //是否忽略大小寫
                        char[] charArray1 = ignoreCase ? obj1.toString().toLowerCase().toCharArray() : obj1.toString().toCharArray();
                        char[] charArray2 = ignoreCase ? obj2.toString().toLowerCase().toCharArray() : obj2.toString().toCharArray();
                        //比較字符串的ASCII碼值
                        for (int i = 0; i < length; i++) {
                            if ((byte) charArray1[i] > (byte) charArray2[i]) {
                                return isAsc ? 1 : -1;
                            } else if ((byte) charArray1[i] < (byte) charArray2[i]) {
                                return isAsc ? -1 : 1;
                            }
                        }
                        //若相同長度部分的字符串都相等,則根據字符串長度比較
                        return isAsc ? (charArray1.length - charArray2.length) : (charArray2.length - charArray1.length);
                    case "java.util.Date":
                        Date d1 = (Date) obj1;
                        Date d2 = (Date) obj2;
                        return d1.getTime() > d2.getTime() ? (isAsc ? 1 : -1) : (isAsc ? -1 : 1);
                    default:
                        throw new RuntimeException("暫不支持 " + type + " 類型的屬性排序");
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
            }
            return 0;
        });

        return list;
    }

}

更多工具類可以查看我的博客:Java字符串、集合等工具類合集
項目源碼地址:全球同性交友網站

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章