首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java List 通用排序方案:反射 + 泛型實現多欄位動態排序

     編輯:Java 相關知識

痛點:重複造輪子的排序代碼

針對 List<UserInfo> 不同欄位排序,傳統寫法需為每個欄位寫一個 Comparator,代碼冗餘嚴重:

Collections.sort(list, new Comparator() {
    public int compare(Object a, Object b) {
        int one = ((UserInfo)a).getUserId();
        int two = ((UserInfo)b).getUserId();
        return one - two;
    }
});

通用解決方案:SortList<E>

利用泛型 + 反射機制,實現任意實體、任意 getter 方法、正/倒序的通用排序:

public class SortList<E> {
    public void sort(List<E> list, final String methodName, final String sortOrder) {
        Collections.sort(list, new Comparator<E>() {
            @Override
            public int compare(E a, E b) {
                int ret = 0;
                try {
                    Method m1 = a.getClass().getMethod(methodName, null);
                    Method m2 = b.getClass().getMethod(methodName, null);
                    
                    Object val1 = m1.invoke(a, null);
                    Object val2 = m2.invoke(b, null);
                    
                    // 統一轉字串比較 (簡化版,實際建議按類型處理)
                    String str1 = val1 != null ? val1.toString() : "";
                    String str2 = val2 != null ? val2.toString() : "";
                    
                    if ("desc".equalsIgnoreCase(sortOrder)) {
                        ret = str2.compareTo(str1); // 倒序
                    } else {
                        ret = str1.compareTo(str2); // 正序
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return ret;
            }
        });
    }
}

使用範例

List<UserInfo> list = new ArrayList<>();
list.add(new UserInfo(3, "b", date("1980-12-01"), 11));
list.add(new UserInfo(1, "c", date("1980-10-01"), 30));
list.add(new UserInfo(2, "a", date("1973-10-01"), 11));

SortList<UserInfo> sorter = new SortList<>();

// 按 userId 倒序
sorter.sort(list, "getUserId", "desc");
// 按 username 正序
sorter.sort(list, "getUsername", "asc");
// 按 birthDate 正序 (需轉字串格式 yyyy-MM-dd)
sorter.sort(list, "getBirthDateStr", "asc");

關鍵技術點解析

進階改良建議

  1. 類型感知比較:判斷返回類型,對數字用 compareTo、日期用 ChronoUnit、字串用 Collator
  2. 快取 Method 對象:避免重複反射查找,提升效能
  3. 支援巢狀屬性:如 "getAddress.getCity" 鏈式調用
  4. Null 安全處理:統一策略 (null 排首/排尾)

現代替代方案 (Java 8+)

使用 Comparator.comparing 鏈式 API 更優雅:

list.sort(Comparator.comparing(UserInfo::getUserId).reversed());
list.sort(Comparator.comparing(UserInfo::getUsername));
list.sort(Comparator.comparing(u -> u.getBirthDate().toString()));

但反射通用方案在「欄位由前端動態傳入」等場景仍具不可替代價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
技術作用注意事項
泛型 <E>類型安全,編譯期檢查運行時類型擦除,需傳 Class 或實例
反射 getMethod動態獲取 getter 方法方法名需符合 JavaBean 規範 (getXxx)
Method.invoke動態調用方法獲取值需處理 IllegalAccess/InvocationTarget 異常
toString 比較統一處理各類型比較日期/數字建議轉標準格式字串 (yyyy-MM-dd)