java8简单入门
1、介紹
本片文章會(huì)從一下幾個(gè)知識(shí)點(diǎn)進(jìn)行介紹:
- 函數(shù)式接口 @FunctionalInterface
- Lambda 表達(dá)式
- 函數(shù)引用 Function Reference
- Stream
看了幾篇關(guān)于 java8 入門的例子,其中引入了許多令人期待已久的特性(雖然我沒有過這樣的體會(huì)),但不管你的代碼是普通青年款還是文藝青年款,你都可以從被 java8 的重新組織的代碼看到她的簡(jiǎn)潔之處,不得不讓我對(duì)這些新入貴圈(java圈)的小鮮肉做一些記錄,以便我能很好的利用他們。
最大的一個(gè)特點(diǎn)莫非就是引入了“函數(shù)式”編程這一個(gè)概念(都是剽竊的別的語言來的),還有那么多新奇的詞語,比如“語法糖”“閉包”“顯式|隱式函數(shù)”等這里我就不再一個(gè)一個(gè)去體會(huì)了,這里屬于初次接觸,先理解會(huì)用為主,細(xì)節(jié)的深入待后期慢慢琢磨。
?
2、函數(shù)式接口 -- @Functionnalinterface
在翠花正式上代碼示例之前,我們現(xiàn)來對(duì)這個(gè)函數(shù)式接口有個(gè)認(rèn)識(shí):
說明:該注解不是必須的,如果一個(gè)接口滿足“函數(shù)式接口”特性,那么不加這個(gè)注解也沒有影響,加上該注解能夠更好的讓編譯器檢查,如果不符合規(guī)范將會(huì)報(bào)編譯錯(cuò)誤。
比如在 jdk8 中就對(duì)Comparator、Callable、Runnable等接口加上了該注解,下面兩段代碼的效果是一樣的:
1 public static void runThreadByLambda() { 2 Runnable runnable = () -> System.out.println("這個(gè)是用拉姆達(dá)實(shí)現(xiàn)的線程"); 3 new Thread(runnable).start(); 4 } 5 6 //--------------------------------------------------------------------------------- 7 public static void runThreadByInnerClass() { 8 Runnable runnable = new Runnable() { 9 @Override 10 public void run() { 11 System.out.println("這個(gè)是用內(nèi)部類實(shí)現(xiàn)的線程"); 12 } 13 }; 14 new Thread(runnable).start(); 15 }
?3、Lambda 表達(dá)式
先用自己的語言來個(gè) Lambda 下個(gè)定義:"一段帶有輸入?yún)?shù)的可執(zhí)行語句塊”。精確與否那是別人的事情,反正我是這么理解的(目前階段是這樣的)。
1 (Type1 param1, Type2 param2, ..., TypeN paramN) -> { 2 statment1; 3 statment2; 4 //............. 5 return statmentM; 6 }對(duì)應(yīng)定義我們自然要給個(gè)例子
1 List<String> names = new ArrayList<>(); 2 names.add("TaoBao"); 3 names.add("ZhiFuBao"); 4 List<String> lowercaseNames = names.stream().map((String name) -> {return name.toLowerCase();}).collect(Collectors.toList());這不就是將一個(gè)集合全部元素變?yōu)樾憜?#xff1f;和我以前用的循環(huán)代碼繁簡(jiǎn)度不想上下,有什么好奇怪的!這位看管不要著急嘛,下面我來個(gè)他搓個(gè)背您再看看如何。
1 List<String> lowercaseNames = names.stream().map(name -> name.toLowerCase()).collect(Collectors.toList()); 2 3 //如果加入方法應(yīng)用就是這樣 4 List<String> lowercaseNames = names.stream().map(String::toLowerCase()).collect(Collectors.toList());簡(jiǎn)化規(guī)則如下:
- 絕大部分情況下,編譯器都可以從上下文推算出參數(shù)類型,因此可以省略
- 當(dāng)參數(shù)只有一個(gè),可以省略小括號(hào)
- 當(dāng)表達(dá)式只包含一條語句時(shí),可以省略大括號(hào)、returned和語句結(jié)尾的分號(hào)
在 Lambda 眼中,外部的變量也是可以訪問的,只是這個(gè)變量默認(rèn)必須是 final ,即便你自己沒有加上,編譯器也會(huì)自動(dòng)幫你加上,所以變大時(shí)內(nèi)部訪問外部變量必須是不可變的(只是引用不可變);還有一個(gè)東西就是 this ,this 在 lambda 指代的不是表達(dá)式生產(chǎn)的那個(gè) SAM(Simple Abstract Method)對(duì)象,而是申明她的外部對(duì)象。
?
4、方法引用(Method reference)和構(gòu)造器引用(Construct reference)
- objectName::instanceMethod ?
- ClassName::staticMethod
例子:System.out::println ? 等同于 ? x -> System.out.println(x)
?????????? Math::max ? ? ? ? ? ? ? ?等同于 ?(x,y) -> Math.max(x,y)
前兩種方法類似,等同于把 Lambda 表達(dá)式的參數(shù)當(dāng)成實(shí)例方法或者靜態(tài)方法的參數(shù)來調(diào)用,下面再來看看第三種情況 - ClassName::instanceMethod
例子:String.toLowerCase ??等同于 ? x -> x.toLowerCase()
等同于把 Lambda 表達(dá)式的第一個(gè)參數(shù)當(dāng)成 實(shí)例方法的目標(biāo)對(duì)象,其余參數(shù)當(dāng)成該方法的參數(shù)來調(diào)用。 - ClassName::new
例子:BigDecimal::new ? ?等同于 ? x -> new BigDecimal(x)
等同于把 Lambda 的參數(shù)當(dāng)成構(gòu)造器的參數(shù)來調(diào)用。
5、Stream
Stream 堪稱 Lambda 的好基友,他們兩個(gè)配合起來使用才能快快樂樂。
-
Stream 是元素的集合,這點(diǎn)讓 Stream 看起來有些類似 iterator
- 可以支持順序和并行的對(duì)原 Stream 進(jìn)行匯聚的操作
?
?
?
?
?
5.1 創(chuàng)建 Stream
// of() 有兩個(gè),變長(zhǎng)參數(shù)和單一參數(shù) Stream<Integer> integerStream = Stream.of(1, 2, 3, 5); Stream<String> stringStream = Stream.of("taobao"); // 匿名類的寫法 Stream.generate(new Supplier<Double>() {@Overridepublic Double get() {return Math.random();} }); // Lambda 寫法 Stream.generate(() -> Math.random); // 函數(shù)引用寫法 Stream.generate(Math::random); // generate() 生產(chǎn)一個(gè)無限長(zhǎng)度的Stream // iterate() 也是生產(chǎn)了一個(gè)無限長(zhǎng)度的 Stream ,其是重復(fù)調(diào)用用戶給定的種子值類獲取元素,seed f(seed) f(f(seed)) ...... Stream.iterate(1, item -> item + 1).limit(10).forEach(System.out::println);除了上面 Stream 的靜態(tài)工廠創(chuàng)建方法之外,就是下面的 Collection 接口的默認(rèn)方法。
1 public interface Collection<E> extends Iterable<E> { 2 //其他方法省略 3 default Stream<E> stream() { 4 return StreamSupport.stream(spliterator(), false); 5 } 6 }5.2? 轉(zhuǎn)換 Stream
顧名思義,就是通過一定的法則將原來的 Stream 轉(zhuǎn)換成一個(gè)新的 Stream,下面列舉一些常用的轉(zhuǎn)換方法來加深理解,一圖勝千言
?
?
?
從以上圖中就可以看出來幾個(gè)常用的 轉(zhuǎn)換函數(shù)的功能,下面我們將大聲的喊出我們的口號(hào)“在一起!”
1 List<Integer> nums = Lists.newArrayList(1,1,null,2,3,4,null,5,6,7,8,9,10); 2 System.out.println(“sum is:”+nums.stream().filter(num -> num != null). 3 distinct().mapToInt(num -> num * 2). 4 peek(System.out::println).skip(2).limit(4).sum());5.3 匯聚(Reduce) Stream
匯聚,也稱為折疊,接受一個(gè)元素序列為輸入,反復(fù)使用某個(gè)合并操作,把序列中的元素合并成一個(gè)匯總的結(jié)果,下面會(huì)分兩部分來介紹匯聚行為。
5.3.1 可變匯聚
把輸入元素累計(jì)到一個(gè)可變的容器中,比如 Collection 或者 StringBuilder。
5.3.2 其他匯聚
除了可變匯聚之外的其余匯聚,一般不是通過反復(fù)修改某個(gè)可變對(duì)象,而是通過把前一次的匯聚結(jié)果當(dāng)成下一次的入?yún)?#xff0c;反復(fù)如此,比如reduce、count、allMatch
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/afanti558/p/7181867.html
總結(jié)
- 上一篇: 【转】Android 将自己的应用改为系
- 下一篇: BZOJ 1070 拆点 费用流