Java - Class fields sort by Collections Class and Comparator interface

看了一下collection的部分,裡面能夠定義的項目除了我們使用的基本型態外,也可以存放物件

,而物件在我們定義它的類別時,會定義很多的欄位(fields),因此當我們要比較兩兩物件是依

據其中一個欄位來達到排序的效果,可以用到Collections Class的sort,而用到它的sort method,

就必須去實作一個comparator來定義您要排序的欄位為何。

基本上,以簡單的成績單為例子,首先自訂Transcript Class

  1. class Transcript{
  2. private String name;
  3. private int Chinese;
  4. private int Math;
  5. private int English;
  6. public Transcript(String name, int Chinese, int Math, int English) {
  7. super();
  8. this.name = name;
  9. this.Chinese = Chinese;
  10. this.Math = Math;
  11. this.English = English;
  12. }
  13. public String getName() {
  14. return name;
  15. }
  16. public int getChinese() {
  17. return Chinese;
  18. }
  19. public int getMath() {
  20. return Math;
  21. }
  22. public int getEnglish() {
  23. return English;
  24. }
  25. }

再來就是定義一個實作了Comparator的類別,如下:
  1. class TranCompare implements Comparator<Transcript>{
  2. private TranSortCommand state;
  3. private String methodName;
  4. public TranCompare(TranSortCommand state, String methodName){
  5. this.state = state;
  6. this.methodName = methodName;
  7. }
  8. @Override
  9. public int compare(Transcript o1, Transcript o2) {
  10. // TODO Auto-generated method stub
  11. try{
  12. Method method1 = o1.getClass().getDeclaredMethod(this.methodName);
  13. Method method2 = o2.getClass().getDeclaredMethod(this.methodName);
  14. Object obj1 = method1.invoke(o1);
  15. Object obj2 = method2.invoke(o2);
  16. if(state == TranSortCommand.NameSort){
  17. return obj1.toString().compareTo(o2.toString());
  18. }else{
  19. if((int)obj1 > (int)obj2){
  20. return -1;
  21. }else if((int)obj1 == (int)obj2){
  22. return 0;
  23. }else{
  24. return 1;
  25. }
  26. }
  27. }catch(Exception e){
  28. e.printStackTrace();
  29. }
  30. return 0;
  31. }
  32. }
TranSortCommand是一個利用enum自訂的型態,程式碼如下:
  1. public enum TranSortCommand{
  2. MathSort, EnglishSort, ChineseSort, NameSort
  3. }

目的是讓 if 做判斷時能夠不以數字來表示要做哪一個項目的排序,使其較具有可讀性。

而透過reflect來呼叫我在Transcript declared的method,使得在分數的排序上,讓相同的判斷

只寫一次就好了,如此我們就要在new TranCompare給予要做哪一個項目的排序及method的

名稱,而排序字串的部分可以return String compareTo method結果,在Collections Class sort也是

有作用的。

再來是主程式的部分:

  1. public class TestComparableInterface {
  2. public static void main(String[] args) {
  3. // TODO Auto-generated method stub
  4. List<Transcript> students = new ArrayList<Transcript>();
  5. Transcript t1 = new Transcript("Ben", 87, 91, 80);
  6. Transcript t2 = new Transcript("sjkok", 94, 99, 65);
  7. Transcript t3 = new Transcript("Aaron", 44, 55, 100);
  8. Transcript t4 = new Transcript("zhibin", 77, 88, 66);
  9. students.add(t1);
  10. students.add(t2);
  11. students.add(t3);
  12. students.add(t4);
  13. Collections.sort(students, new TranCompare(TranSortCommand.MathSort, "getMath"));
  14. //Collections.reverse(students);
  15. for(Transcript t : students){
  16. System.out.println("Name:"+t.getName()+"\tChinese:"+t.getChinese()+"\tMath:"+t.getMath()+"\tEnglish:"+t.getEnglish());
  17. }
  18. }
  19. }

透過Collections.sort,帶進List and 您定義的comparator,如此再印出資料時就可以達到某項目

排序的效果!如下:



留言