針對 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;
}
});
利用泛型 + 反射機制,實現任意實體、任意 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");
| 技術 | 作用 | 注意事項 |
|---|---|---|
| 泛型 <E> | 類型安全,編譯期檢查 | 運行時類型擦除,需傳 Class 或實例 |
| 反射 getMethod | 動態獲取 getter 方法 | 方法名需符合 JavaBean 規範 (getXxx) |
| Method.invoke | 動態調用方法獲取值 | 需處理 IllegalAccess/InvocationTarget 異常 |
| toString 比較 | 統一處理各類型比較 | 日期/數字建議轉標準格式字串 (yyyy-MM-dd) |