前言
目前我們知道java的版本已經發布到12了,之前的項目用的是JDK1.7,聽說JDK1.8的改動相對來說大一些,因此抽空學學JDK1.8的一些新特性。本人也是通過閱讀Java8實戰這本書做一些小的總結,方便以后鞏固,同時也為想學習Java1.8的人提供一些思路望大家多多包涵,有不對的地方請提出了我們一起學習。想要Java8實戰這本書電子版的小伙伴可以留言告我可以發給你呦!
演變過程
這里我們通過一個簡單的故事來引出神奇的Lambda。這里首先有一個蘋果的實例,其包含簡單的屬性:顏色和重量。
1 public class Apple { 2 private int weight = 0; 3 private String color = ""; 4 5 public Apple(int weight, String color){ 6 this.weight = weight; 7 this.color = color; 8 } 9 // get/set/toString 10 }
首先我們要獲取紅色的蘋果(因為紅色的好吃嘛),這時候我們會定義一個簡單的方法來進行過濾獲取到紅色的蘋果。
1 /** 2 * 篩選紅蘋果 3 * @param inventory 4 * @return 5 */ 6 public static List<Apple> filterRedApples(List<Apple> inventory){ 7 List<Apple> result = new ArrayList<>(); 8 9 for (Apple apple: inventory){ 10 if ("red".equals(apple.getColor())) { 11 result.add(apple); 12 } 13 } 14 15 return result; 16 }
后來由於蘋果收購商有來了,我不管什么蘋果,只要重量大於150g的統統給我裝上車!好辦啦!我們再加個方法來進行過濾就可以了。
/** * 篩選重量大於150的蘋果 * @param inventory * @return */ public static List<Apple> filterHeavyApples(List<Apple> inventory){ List<Apple> result = new ArrayList<>(); for (Apple apple: inventory){ if (apple.getWeight() > 150) { result.add(apple); } } return result; }
過了幾天水果商又來了,我們現在想要綠色的蘋果。這時候你可能想到是加一個方法 filterGreenApples 專門過濾綠色蘋果,然而,如果要篩選多種顏色呢?黃色?暗紅色?難道我們要每個新加一個方法嗎?當然不是!我們最開始想到的是吧顏色作為參數傳進去,試着將其抽象化。
1 public static List<Apple> filterApplesByColor(List<Apple> inventory, 2 String color) { 3 List<Apple> result = new ArrayList<Apple>(); 4 5 for (Apple apple: inventory){ 6 if ( apple.getColor().equals(color) ) { 7 result.add(apple); 8 } 9 } 10 11 return result; 12 }
同時我們可能想到將獲取重量的方法也進行優化
1 public static List<Apple> filterApplesByWeight(List<Apple> inventory, 2 int weight) { 3 List<Apple> result = new ArrayList<Apple>(); 4 5 for (Apple apple : inventory){ 6 if ( apple.getWeight() > weight ){ 7 result.add(apple); 8 } 9 } 10 11 return result; 12 }
這時候就很不錯了,可(cao)愛(dan)的水果商又來了讓我們提供一種方式來區分不同的屬性進行過濾。OK! 我們進行優化!
1 public static List<Apple> filterApples(List<Apple> inventory, String color, 2 int weight, boolean flag) { 3 List<Apple> result = new ArrayList<Apple>(); 4 5 for (Apple apple: inventory){ 6 if ( (flag && apple.getColor().equals(color)) || 7 (!flag && apple.getWeight() > weight) ){ 8 result.add(apple); 9 } 10 } 11 12 return result; 13 }
你會發現這個方法中的flag很難讓人讀懂。而且如果水果商想要再根據不同的屬性進行過濾呢?比如產地、形狀,那么這個方案就不能滿足我們的需求了。
那么我們如何應對這種多變的需求呢?讓我們來定義一個接口對蘋果過濾器進行建模。
1 public interface AppleFilter { 2 boolean test(Apple apple); 3 }
我們定義一個接口對蘋果進行過濾,你可以定義多個實現類來選擇不同的標准。
1 public class AppleGreenColorFiler implements AppleFilter { 2 @Override 3 public boolean test(Apple apple) { 4 return "green".equals(apple.getColor()); 5 } 6 } 7 8 public class AppleHeavyWeightFilter implements AppleFilter { 9 @Override 10 public boolean test(Apple apple){ 11 return apple.getWeight() > 150; 12 } 13 }
這種實現方式類似與策略模式,我們可以將這種行為的實現作為一個參數傳遞進去。
1 public static List<Apple> filterApples(List<Apple> inventory, AppleFilter appleFilter) { 2 List<Apple> result = new ArrayList<Apple>(); 3 4 for (Apple apple : inventory) { 5 if(appleFilter.test(apple)) { 6 result.add(apple); 7 } 8 } 9 10 return result; 11 }
這時候我們會發現我們的代碼靈活很多了,可以應對水果商的各種需求了。而過濾的主要業務我們是在其實現類中進行定義的。我們甚至可以同時獲取重量大於150並且是紅色的蘋果。
1 public class AppleRedAndHeavyFilter implements AppleFilter { 2 @Override 3 public boolean test(Apple apple) { 4 return "red".equals(apple.getColor()) && apple.getWeight() > 150; 5 } 6 }
這時候我們發現我們可以使用匿名內部類做代碼的優化。並不需要每次都創建其實現類來完成。
1 List<Apple> redApples = filterApples(inventory, new AppleFilter() { 2 @Override 3 public boolean test(Apple apple) { 4 return "red".equals(apple.getColor()); 5 } 6 });
那么在Java8中我們怎么做呢?看好啦!
1 List<Apple> redApples = filterApples(inventory, (Apple apple) -> "red".equals(apple.getColor()));
這樣的代碼即簡潔又容易讀懂。
其他例子
其實這樣的寫法可以針對很多地方,例如我們在使用Comparator對集合中的數據進行排序的時候,再比如使用Runnable創建線程的時候。這里就不再舉例了,希望大家自己在下面試試這幾種方式。