最近看到這樣一段排序的代碼。
public static List<?> getBrandOrderList(List<?> list, String Field) { String[] brandArr = {"7天", "7天優品", "IU", "派", "麗楓", "喆啡", "希岸", "歡朋", "潮漫", "ZMAX", "非繁&城品"}; Comparator typeComparator = new FixedOrderComparator(brandArr); Comparator indexTypeComparator = new BeanComparator(Field, typeComparator); Collections.sort(list, indexTypeComparator); return list; }
后來了解到,這段代碼是為了實現:對傳入的列表list按照對象的屬性Field排序,而順序要和數組brandArr一致。
首先,我們常常會遇到需要對javaBean排序的情況,如果是對javaBean的單一屬性排序,可以直接使用BeanComparator實現自然排序(根據ASCII碼排序)
代碼入下:
1 List<Student> list = new ArrayList<>(); 2 list.add(new Student("張三",1)); 3 list.add(new Student("王五",1)); 4 list.add(new Student("李四",1)); 5 list.add(new Student("趙六",1)); 6 System.out.println(list); 7 BeanComparator beanComparator = new BeanComparator("name"); 8 Collections.sort(list,beanComparator); 9 System.out.println(list);
運行結果如下:
[Student(name=張三, age=1), Student(name=王五, age=1), Student(name=李四, age=1), Student(name=趙六, age=1)]
排序后:
[Student(name=張三, age=1), Student(name=李四, age=1), Student(name=王五, age=1), Student(name=趙六, age=1)]
這里有一個非常巧合的事情,就是根據ASCII排序,張 李 王 趙是順序排列的。
但是這里有一定的限制,傳入的排序字段必須存在,並且要提供get方法。還有就是只能對單個屬性排序,如果要對多個屬性排序,僅僅使用BeanComparator是不能完成的。具體的解決方案后邊會提到。
而工作中往往會有定制化的需求,那如果要對對象按照指定的順序排序,就需要FixedOrderComparator實現定制化的排序規則。
1 List<Student> list = new ArrayList<Student>(){ 2 { 3 add(new Student("張三",28)); 4 add(new Student("王五",23)); 5 add(new Student("李四",26)); 6 add(new Student("趙六",17)); 7 } 8 }; 9 //指定排序規則,參數可以使集合,數組或可變參數 10 FixedOrderComparator fixedOrderComparator = new FixedOrderComparator("張三","李四","王五","趙六"); 11 //將要排序的屬性,和自定義排序規則傳入 12 BeanComparator beanComparator = new BeanComparator("name",fixedOrderComparator); 13 //排序操作 14 Collections.sort(list,beanComparator); 15 System.out.println(list);
輸出:
[Student(name=張三, age=28), Student(name=李四, age=26), Student(name=王五, age=23), Student(name=趙六, age=17)]
這也就是開頭提到的例子實現的功能。
另外,如果要實現多元素排序,需要用到ComparatorChain
1 List<Student> list = new ArrayList<Student>(){ 2 { 3 add(new Student("張三",28)); 4 add(new Student("王五",23)); 5 add(new Student("李四",26)); 6 add(new Student("李四",23)); 7 add(new Student("趙六",17)); 8 } 9 }; 10 ComparatorChain comparatorChain = new ComparatorChain(); 11 //按照名稱排序 12 FixedOrderComparator nameComparator = new FixedOrderComparator("張三","李四","王五","趙六"); 13 BeanComparator nameBeanComparator = new BeanComparator("name",nameComparator); 14 //按照年齡排序 15 FixedOrderComparator ageComparator = new FixedOrderComparator(28,26,23,17); 16 BeanComparator ageBeanComparator = new BeanComparator("age",ageComparator); 17 //加入排序規則 18 comparatorChain.addComparator(nameBeanComparator); 19 comparatorChain.addComparator(ageBeanComparator); 20 //排序操作 21 Collections.sort(list,comparatorChain); 22 System.out.println(list);
輸出:
[Student(name=張三, age=28), Student(name=李四, age=26), Student(name=李四, age=23), Student(name=王五, age=23), Student(name=趙六, age=17)]
可以看到,在名稱排序相同的情況下,李四是按照26在前,23在后的順序排列的
其中的坑:
1.對象屬性提供get方法
2.如果要實現定制化排序,定制化的排序規則中,必須要包含所有排序列可能出現的值(比如說:集合中出現的所有age值,在new FixedOrderComparator(28,26,23,17)中必須全部出現,否則會出現java.lang.IllegalArgumentException: Attempting to compare unknown object xx這樣的報錯。
總之,通過這三個對象,可以實現Bean對象的定制化多規則排序,具體實現根據需求來決定。