【JDK8】排序策略的實作
前情 << 【JDK8】從 synchronized、Lock 到 StampedLock 在收集物件之後,對物件進行排序是常用的動作,JDK8 之前,基本上可使用 搭配 Lambda 來排序如果你使用 JDK8,因為 List<String> words = Arrays.asList("B", "X", "A", "M", "F", "W", "O"); Collections.sort(words, (s1, s2) -> -s1.compareTo(s2)); List 的 sort 與 Stream 的 sorted實際上,JDK8 在 List<String> words = Arrays.asList("B", "X", "A", "M", "F", "W", "O"); words.sort((s1, s2) -> -s1.compareTo(s2)); 如果只是想使用 List<String> words = Arrays.asList("B", "X", "A", "M", "F", "W", "O"); words.sort(String::compareTo); 以上的排序,會直接在原有的 List<String> words = Arrays.asList("B", "X", "A", "M", "F", "W", "O") .stream() .sorted() .collect(toList());
在管線化操作時若使用 附帶一提的是, Comparator 的靜態方法JDK8 中,介面上也可以定義靜態方法, public class NullFirstStrLengthComparator implements Comparator<String> { @Override public int compare(String s1, String s2) { if(s1 == null) { return -1; } if(s2 == null) { return 1; } if(s1.length() == s2.length()) { return 0; } if(s1.length() > s2.length()) { return -1; } return 1; } } 不怎麼好讀,對吧!更別說為了表示這個比較器的目的,必須取個又臭又長的類別名稱!其實排序會有各式各樣的組合需求,JDK8 考量到這點,為排序加入了一些高階語義 API,例如 以方才的需求為例,在 JDK8 中要建立對應的 package cc.openhome; import java.util.*; import static java.util.Comparator.*; import static java.lang.System.out; public class Sort6 { public static void main(String[] args) { List words = Arrays.asList( "B", "X", "A", "M", null ,"F", "W", "O", null); Collections.sort(words, nullsFirst(comparingInt(String::length))); out.println(words); // [null, null, X, W, O, M, F, B, A] } }
Comparator 的預設方法JDK8 中,介面上也可以定義預設方法(Default method),實際上, 例如,你可能想要排序時先依客戶的姓來排,如果姓相同再依名來排,如果姓名都相同,再依他們居住地的郵遞區號來排,那麼你可以如下建立 package cc.openhome; import static java.lang.System.out; import java.util.*; import static java.util.Comparator.comparing; public class CustomerDemo { public static void main(String[] args) { List<Customer> customers = Arrays.asList( new Customer("Justin", "Lin", 804), new Customer("Monica", "Huang", 804), new Customer("Irene", "Lin", 804) ); Comparator<Customer> byLastName = comparing(Customer::getLastName); customers.sort( byLastName .thenComparing(Customer::getFirstName) .thenComparing(Customer::getZipCode) ); customers.forEach(out::println); } } class Customer { private String firstName; private String lastName; private Integer zipCode; public Customer(String firstName, String lastName, Integer zipCode) { this.firstName = firstName; this.lastName = lastName; this.zipCode = zipCode; } public String toString() { return String.format("Customer(%s %s, %d)", firstName, lastName, zipCode); } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public Integer getZipCode() { return zipCode; } } 每次 如果你沒有使用 JDK8,基本上在 guava-libraries 上,也可以取得這類高階排序 API,這部份的內容可以參考 【Guava 教學】(3)高階排序概念的實現。 |