根據名稱的長度進行排序,可以如下撰寫程式:
List<String> names = Arrays.asList("Justin", "Monica", "Irene", "caterpillar");
Collections.sort(names, new Comparator<String>() {
    public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }
});compare 的方法本體實作,並不容易看出程式碼要做些什麼。你也許還會有其他的排序策略,因此,你在 StringOrder 類別中,定義了幾個 static 方法:
      public class StringOrder {
    public static int byLength(String s1, String s2) {
        return s1.length() - s2.length();
    }
    public static int byLexicography(String s1, String s2) {
        return s1.compareTo(s2);
    }
    public static int byLexicographyIgnoreCase(String s1, String s2) {
        return s1.compareToIgnoreCase(s2);
    }
    ...
}Collections.sort(names, new Comparator<String>() {
    public int compare(String s1, String s2) {
        return StringOrder.byLength(s1, s2);
    }
});Collections.sort(names, (s1, s2) -> NameOrder.byLength(s1, s2));byLength 方法的簽署與 Comparator 的 compare 方法相同。我們知道,Lambda 運算式是匿名方法(函式),而 Lambda 運算式的本體部份就是函式介面(Functional interface)的方法實作。因為我們只是把參數 s1 與 s2 傳給 byLength 方法,那麼可以直接重用 byLength 方法的實作不是更好嗎?是的,JDK8 提供了方法可參考的特性,可以達到這個目的:
      Collections.sort(names, NameOrder::byLength);static 方法。你也可以參考至特定型態的任意物件之實例方法。例如,按照字典順序對名稱清單進行排序,原本可以如下撰寫:
      Collections.sort(names, NameOrder::byLexicography);NameOrder::byLexicography 會參考到 byLexicography 方法實作,而以下的程式碼也有相同的排序效果:
      Collections.sort(names, (s1, s2) -> s1.compareTo(s2));s1 會是 compareTo 的接受者,而第二個參數 s2 則是 compareTo 方法的引數,在這種情況下,其實我們可以直接參考 String 類別的 compareTo 方法,像是:
      Collections.sort(names, String::compareTo);static 方法來達到:
      Collections.sort(names, NameOrder::byLexicographyIgnoreCase);byLexicographyIgnoreCase 的方法實作中,第一個參數是 compareToIgnoreCase 方法的接受者,而第二個參數是 compareToIgnoreCase 方法的引數,此時,我們可以直接參考 String 類別的 compareToIgnoreCase 方法。
      Collections.sort(names, String::compareToIgnoreCase);public class JobVacancy {
    ...
    public int bySeniority(JobApplicant ja1, JobApplicant ja2) {
        ...
    }
    public int byEducation(JobApplicant ja1, JobApplicant ja2) {
        ...
    }
    ...
}public class JobApplicant {
    ...
}List<JobApplicant> applicants = ...;
JobVacancy vacancy = ...;
Collections.sort(applicants, (ja1, ja2) -> vacancy.bySeniority(ja1, ja2));vacancy 參考的物件。bySeniority 方法的簽署與 Comparator 的 compare 方法相同,此時,我們可以直接參考 vacancy 物件的 bySeniority 方法。
      Collections.sort(applicants, vacancy::bySeniority);public interface Part {
    ...
}public interface Material {
    ...
}public interface PartFactory {
    Part createPart(Material material);
}public class PartImpl implements Part {
    public PartImpl(Material material) {
        ...
    }
}public class MaterialImpl implements Material {
    ...
}public PartFactoryImpl implements PartFactory {
    public Part createPart(Material material) {
        return new PartImpl(material);
    }
}Part 實例:
      PartFactory factory = new PartFactoryImpl();
Part part = factory.createPart(new MaterialImpl());createPart 方法的實作中,只是使用建構式來建立了 Part 的實例。使用 JDK8 的話,你就不用特別花時間定義 PartFactoryImpl 類別,你可以直接參考 PartImpl 的建構式。
      PartFactory factory = PartImpl::new;
Part part = factory.createPart(new MaterialImpl());終於,〈認識 Lambda/Closure〉要告一段落了。「等一下!怎麼沒討論預設方法(Default method)?那不是 Lambda 專案的一部份嗎?」
是的,預設方法確實是 Lambda 專案的一部份,不過他跟將現在的 API 演化有關。預設方法解除了介面上的一些限制,讓 Java 介面在進行防禦式(Defensive)的 API 演化時容易一些,並為流程的重用開啟了更多可能性,不過,也帶入多重繼承上的一些複雜度。在討論如何將現在的 API 演化的時候,我們也許會看到一些函數式程式設計(Functional programming)的影子。我想,用一個新的系列來討論這些有趣的主題,會是比較好的做法,所以這些會留到下一個系列〈Java 開發者的函數式程式設計〉中來討論。

