JDK8 新特性 Lambda表達式


1.java8中Lambda表達式基礎語法:

(x,y) -> {}

左側是一個小括號,里面是要實現的抽象方法的參數,有幾個參數就寫幾個參數名,無參可寫空括號,無需聲明參數類型;

中間是一個jdk8新定義的箭頭符號;

右側是一個大括號,在括號內編寫抽象方法的實現內容,有參時,可直接使用左側括號中的對應參數,與正常方法的方法體相同;

使用方式:實現只有一個抽象方法的接口時會自行匹配到該方法,在箭頭左側編寫對應參數個數的參數名,箭頭右側編寫方法的實現代碼(代碼實現為單行時可去掉大括號{})

 示例:

 1     @Test
 2     public void test() {
 3         //輸入一個數,與100比較大小
 4 
 5         //實現方式1 匿名內部類:
 6         Comparable<Integer> comparable1 = new Comparable<Integer>() {
 7             @Override
 8             public int compareTo(Integer o) {
 9                 return Integer.compare(o, 100);
10             }
11         };
12         comparable1.compareTo(2);
13 
14         //實現方式2 Lambda表達式:實現只有一個抽象方法的Comparable接口時會自行匹配到compareTo方法,在箭頭左側編寫對應參數個數的參數名,箭頭右側編寫方法的實現代碼
15         Comparable<Integer> comparable2 = (x) -> Integer.compare(x, 100);
16         comparable2.compareTo(2);
17     }

 

2.Lambda表達式的函數式編程需要函數式接口(有且只有一個抽象方法的接口)的支持,為了防止使用Lambda表達式時都必須手動添加接口,Java8內置了四大核心函數式接口:

/**
* Java8內置的四大核心函數式接口
*
* Consumer<T> :消費型接口
* void acept(T t);
*
* Supplier<T> :供給型接口
* T get();
*
* Function<T,R> :函數型接口
* R apply(T t);
*
* Predicate<T> :斷言型接口
* boolean test(T t);
*/

 1     public static void main(String[] args) {
 2         //內置函數式接口使用示例
 3 
 4         //消費型接口Consumer,輸入一個參數,對其進行打印輸出
 5         Consumer<String> consumer = (x) -> System.out.println(x);
 6         //打印字符串
 7         consumer.accept("hehe");
 8 
 9         //供給型接口Supplier,返回指定字符串
10         Supplier<String> supplier = () -> "Hello world!";
11         //獲取字符串
12         supplier.get();
13 
14         //函數型接口Function,輸入字符串,返回字符串長度
15         Function<String, Integer> function = (x) -> x.length();
16         //獲取字符串長度
17         function.apply("Hello world!");
18 
19         //斷言型接口Predicate,輸入數字,判斷是否大於0
20         Predicate<Integer> predicate = (x) -> x > 0;
21         //獲取判斷結果
22         predicate.test(10);
23     }

除了這四個接口外還有其他多參數的子接口,自行查找。


3.某些情況下要實現的業務部分已有方法實現,可直接引用該方法,此時可使用Lambda表達式中的方法引用:

/**
* 方法引用:若Lambda體中的內容有方法已經實現了,我們可以使用“方法引用”
* 可以理解為方法引用是lambda表達式的另外一種表達形式
*
* 主要有三種語法格式:
*
* 對象::實例方法名
*
* 類::靜態方法名
*
* 類::實例方法名
*/
方法引用注意點:被引用的方法的參數和返回值必須和要實現的抽象方法
的參數和返回值一致
1         //引用out對象的打印輸出方法作為Consumer接口accept方法的具體實現
2         Consumer<String> consumer1 = System.out::println;
3         consumer1.accept("hehe");
4         
5         //lambda表達式常用方式
6         BiPredicate<String, String> bp1 = (x, y) -> x.equals(y);
7         //方法引用:類::實例方法(方法傳入參數是兩個參數,且第一個參數作為方法調用對象,第二個參數作為調用的方法的參數)
8         BiPredicate<String, String> bp2 = String::equals;

 4.構造器引用:通過函數式接口實例化類時可進行構造器引用

注意點:引用到的是與函數式接口中的方法參數個數及類型相同的構造器

1         //lambda表達式常用方式
2         Supplier<Passenger> supplier1 = () -> new Passenger();
3         //構造器引用:通過類型推斷,引用無參構造器
4         Supplier<Passenger> supplier2 = Passenger::new;
5       
6         //lambda表達式常用方式
7         BiFunction<String, String, Passenger> function1 = (x, y) -> new Passenger(x, y);
8         //構造器引用:通過類型推斷,引用有兩個String參數的構造器
9         BiFunction<String, String, Passenger> function2 = Passenger::new;

5.數組引用:

1         //lambda表達式常用方式
2         Function<Integer, String[]> fun1 = (x) -> new String[x];
3         String[] strs1 = fun1.apply(10);
4         //數組引用
5         Function<Integer, String[]> fun2 = String[]::new;
6         String[] strs2 = fun2.apply(10);

6.Stream流的應用

Stream的使用步驟:
1 創建Stream對象
2 執行中間操作
3 執行終止操作

1)Stream對象的創建方式:

 1     /**
 2      * Stream的使用:
 3      * 1 創建Stream對象
 4      * 2 中間操作
 5      * 3 終止操作
 6      */
 7     public static void main(String[] args) {
 8         //stream對象獲取方式:
 9         String[] strings = {"1", "2", "3", "4"};
10         
11         //方式1:數組獲取stream對象
12         Stream<String> stream1 = Arrays.stream(strings);
13         
14         //方式2:集合獲取stream對象
15         List<String> list = Arrays.asList(strings);
16         Stream<String> stream2 = list.stream();
17         
18         //方式3:Stream靜態方法of獲取stream對象
19         Stream<String> stream3 = Stream.of(strings);
20         
21         //方式4:創建無限流(seed起始值,重復無限次執行的方法)
22         //無限流1:迭代
23         Stream<Integer> stream4 = Stream.iterate(0, x -> x + 2);
24         //無限流2:生成
25         Stream<Double> stream5 = Stream.generate(() -> Math.random());
26     }

2)Stream常用中間操作方法:

 1         //Stream常用方法(鏈式方法,從上往下執行,下一個方法進行處理的對象是上一個方法處理后的結果)
 2         Arrays.stream(new Integer[]{1, 63, 3, 7, 11, 54, 34})
 3                 //過濾器,傳入一個Predicate斷言型接口實現,Stream會進行內部遍歷,將保留斷言返回true的元素(此處過濾保留值大於4的元素)
 4                 .filter(x -> x > 4)
 5                 //截斷流,只獲取前n個元素(此處獲取滿足過濾器條件的前2個元素)
 6                 .limit(5)
 7                 //跳過元素,跳過前n個元素,獲取后面的元素,若流中的元素不足n個,則返回一個空流,與limit互補(此處取除第一個元素外的元素)
 8                 .skip(1)
 9                 //映射,對流內元素進行處理,可以是轉換類型、獲取屬性值等等,傳入一個Function函數型接口實現(此處對流內元素全部加5)
10                 .map(x -> x + 5)
11                 //自然排序(按照Comparable默認排序,此處為Integer從小到大排序)
12                 .sorted()
13                 //定制排序(按照Comparator自定義排序,此處處理為Integer從大到小排序)
14                 .sorted((x, y) -> -Integer.compare(x, y))
15                 //終止操作,遍歷流內元素,傳入一個Consumer消費型接口實現(此處簡單對流內元素進行打印輸出)
16                 .forEach(System.out::println);

3)Stream常用終止操作方法:

 

 1         //終止操作
 2         Integer[] integers = {1, 63, 3, 7, 11, 54, 34};
 3         List<Integer> list = Arrays.asList(integers);
 4 
 5         //匹配所有元素,傳入一個Predicate斷言型接口實現,當所有元素都滿足條件時返回true,否則返回false(此處判斷元素是否全部大於0)
 6         boolean b1 = list.stream().allMatch(x -> x > 0);
 7 
 8         //匹配元素,傳入一個Predicate斷言型接口實現,當有至少一個元素滿足條件時返回true,否則返回false(此處判斷元素是否全部大於0)
 9         boolean b2 = list.stream().anyMatch(x -> x > 0);
10 
11         //無匹配元素,傳入一個Predicate斷言型接口實現,沒有元素滿足條件時返回true,否則返回false(此處判斷元素是否全部大於0)
12         boolean b3 = list.stream().noneMatch(x -> x > 0);
13 
14         //匹配第一個元素
15         Optional<Integer> o4 = list.stream().findFirst();
16 
17         //匹配任意一個元素
18         Optional<Integer> o5 = list.stream().findAny();
19 
20         //獲取流中元素個數
21         long l6 = list.stream().count();
22 
23         //獲取流中滿足條件的最小值
24         Optional<Integer> min = list.stream().min(Integer::compare);
25         System.out.println("min:" + min.get());
26 
27         //獲取流中滿足條件的最大值
28         Optional<Integer> max = list.stream().max(Integer::compare);
29         System.out.println("max:" + max.get());
30 
31         //歸約(將identity作為起始x,第一個元素作為y,計算結果再作為x與下一個元素進行計算,得出計算結果)
32         Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
33         //歸約(未設置起始x,因此有可能空指針,因此返回類型為Optional)
34         Optional<Integer> reduce1 = list.stream().reduce(Integer::sum);
35 
36         //收集(將流轉換為其他形式,接受一個Collector接口實現,用於給Stream中元素做匯總的方法)
37         List<Integer> collect = list.stream().collect(Collectors.toList());
38         //轉為hashset
39         HashSet<Integer> collect1 = list.stream().collect(Collectors.toCollection(HashSet::new));
40         //取平均值
41         Double collect2 = list.stream().collect(Collectors.averagingInt((x) -> x));
42         System.out.println("avg:" + collect2);
43         //求和
44         Double collect3 = list.stream().collect(Collectors.summingDouble(x -> x));
45         System.out.println("sum:" + collect3);

 

待續。。。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM