函数式编程-Stream流
1. 概述
1.1 為什么學(xué)?
-
能夠看懂公司里的代碼
-
大數(shù)量下處理集合效率高
-
代碼可讀性高
-
消滅嵌套地獄
1.2 函數(shù)式編程思想
1.2.1 概念
面向?qū)ο笏枷胄枰P(guān)注用什么對象完成什么事情。而函數(shù)式編程思想就類似于我們數(shù)學(xué)中的函數(shù)。它主要關(guān)注的是對數(shù)據(jù)進(jìn)行了什么操作。
1.2.2 優(yōu)點
-
代碼簡潔,開發(fā)快速
-
接近自然語言,易于理解
-
易于"并發(fā)編程"
2. Lambda表達(dá)式
2.1 概述
Lambda是JDK8中一個語法糖。他可以對某些匿名內(nèi)部類的寫法進(jìn)行簡化。它是函數(shù)式編程思想的一個重要體現(xiàn)。讓我們不用關(guān)注是什么對象。而是更關(guān)注我們對數(shù)據(jù)進(jìn)行了什么操作。
2.2 核心原則
可推導(dǎo)可省略
2. 3 基本格式
(參數(shù)列表)->{代碼}例一
我們在創(chuàng)建線程并啟動時可以使用匿名內(nèi)部類的寫法:
new Thread(new Runnable() {@Overridepublic void run() {System.out.println("你知道嗎 我比你想象的 更想在你身邊");} }).start();可以使用Lambda的格式對其進(jìn)行修改。修改后如下:
new Thread(()->{System.out.println("你知道嗎 我比你想象的 更想在你身邊"); }).start();例二:
現(xiàn)有方法定義如下,其中IntBinaryOperator是一個接口。先使用匿名內(nèi)部類的寫法調(diào)用該方法。
?public static int calculateNum(IntBinaryOperator operator){int a = 10;int b = 20;return operator.applyAsInt(a, b);} ?public static void main(String[] args) {int i = calculateNum(new IntBinaryOperator() {@Overridepublic int applyAsInt(int left, int right) {return left + right;}});System.out.println(i);}Lambda寫法:
? ?public static void main(String[] args) {int i = calculateNum((int left, int right)->{return left + right;});System.out.println(i);}例三:
現(xiàn)有方法定義如下,其中IntPredicate是一個接口。先使用匿名內(nèi)部類的寫法調(diào)用該方法。
? ?public static void printNum(IntPredicate predicate){int[] arr = {1,2,3,4,5,6,7,8,9,10};for (int i : arr) {if(predicate.test(i)){System.out.println(i);}}}public static void main(String[] args) {printNum(new IntPredicate() {@Overridepublic boolean test(int value) {return value%2==0;}});}Lambda寫法:
? ?public static void main(String[] args) {printNum((int value)-> {return value%2==0;});}public static void printNum(IntPredicate predicate){int[] arr = {1,2,3,4,5,6,7,8,9,10};for (int i : arr) {if(predicate.test(i)){System.out.println(i);}}}例四:
現(xiàn)有方法定義如下,其中Function是一個接口。先使用匿名內(nèi)部類的寫法調(diào)用該方法。
? ?public static <R> R typeConver(Function<String,R> function){String str = "1235";R result = function.apply(str);return result;}public static void main(String[] args) {Integer result = typeConver(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.valueOf(s);}});System.out.println(result);}Lambda寫法:
? ? ? ?Integer result = typeConver((String s)->{return Integer.valueOf(s);});System.out.println(result); ?例五:
現(xiàn)有方法定義如下,其中IntConsumer是一個接口。先使用匿名內(nèi)部類的寫法調(diào)用該方法。
? ?public static void foreachArr(IntConsumer consumer){int[] arr = {1,2,3,4,5,6,7,8,9,10};for (int i : arr) {consumer.accept(i);}}public static void main(String[] args) {foreachArr(new IntConsumer() {@Overridepublic void accept(int value) {System.out.println(value);}});}Lambda寫法:
? ?public static void main(String[] args) {foreachArr((int value)->{System.out.println(value);});}2.4 省略規(guī)則
-
參數(shù)類型可以省略
-
方法體只有一句代碼時大括號return和唯一一句代碼的分號可以省略
-
方法只有一個參數(shù)時小括號可以省略
-
以上這些規(guī)則都記不住也可以省略不記
3. Stream流
3.1 概述
Java8的Stream使用的是函數(shù)式編程模式,如同它的名字一樣,它可以被用來對集合或數(shù)組進(jìn)行鏈狀流式的操作。可以更方便的讓我們對集合或數(shù)組操作。
3.2 案例數(shù)據(jù)準(zhǔn)備
? (導(dǎo)入依賴) <dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version></dependency></dependencies> @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode//用于后期的去重使用 public class Author {//idprivate Long id;//姓名private String name;//年齡private Integer age;//簡介private String intro;//作品private List<Book> books; } @Data @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode//用于后期的去重使用 public class Book {//idprivate Long id;//書名private String name; ?//分類private String category; ?//評分private Integer score; ?//簡介private String intro; ? } ? ?private static List<Author> getAuthors() {//數(shù)據(jù)初始化Author author = new Author(1L,"蒙多",33,"一個從菜刀中明悟哲理的祖安人",null);Author author2 = new Author(2L,"亞拉索",15,"狂風(fēng)也追逐不上他的思考速度",null);Author author3 = new Author(3L,"易",14,"是這個世界在限制他的思維",null);Author author4 = new Author(3L,"易",14,"是這個世界在限制他的思維",null); ?//書籍列表List<Book> books1 = new ArrayList<>();List<Book> books2 = new ArrayList<>();List<Book> books3 = new ArrayList<>(); ?books1.add(new Book(1L,"刀的兩側(cè)是光明與黑暗","哲學(xué),愛情",88,"用一把刀劃分了愛恨"));books1.add(new Book(2L,"一個人不能死在同一把刀下","個人成長,愛情",99,"講述如何從失敗中明悟真理")); ?books2.add(new Book(3L,"那風(fēng)吹不到的地方","哲學(xué)",85,"帶你用思維去領(lǐng)略世界的盡頭"));books2.add(new Book(3L,"那風(fēng)吹不到的地方","哲學(xué)",85,"帶你用思維去領(lǐng)略世界的盡頭"));books2.add(new Book(4L,"吹或不吹","愛情,個人傳記",56,"一個哲學(xué)家的戀愛觀注定很難把他所在的時代理解")); ?books3.add(new Book(5L,"你的劍就是我的劍","愛情",56,"無法想象一個武者能對他的伴侶這么的寬容"));books3.add(new Book(6L,"風(fēng)與劍","個人傳記",100,"兩個哲學(xué)家靈魂和肉體的碰撞會激起怎么樣的火花呢?"));books3.add(new Book(6L,"風(fēng)與劍","個人傳記",100,"兩個哲學(xué)家靈魂和肉體的碰撞會激起怎么樣的火花呢?")); ?author.setBooks(books1);author2.setBooks(books2);author3.setBooks(books3);author4.setBooks(books3); ?List<Author> authorList = new ArrayList<>(Arrays.asList(author,author2,author3,author4));return authorList;}3.3 快速入門
3.3.1 需求
我們可以調(diào)用getAuthors方法獲取到作家的集合?,F(xiàn)在需要打印所有年齡小于18的作家的名字,并且要注意去重。
3.3.2 實現(xiàn)
? ? ? ?//打印所有年齡小于18的作家的名字,并且要注意去重List<Author> authors = getAuthors();authors.stream()//把集合轉(zhuǎn)換成流.distinct()//先去除重復(fù)的作家.filter(author -> author.getAge()<18)//篩選年齡小于18的.forEach(author -> System.out.println(author.getName()));//遍歷打印名字3.4 常用操作
3.4.1 創(chuàng)建流
單列集合: 集合對象.stream()
? ? ? ?List<Author> authors = getAuthors();Stream<Author> stream = authors.stream();數(shù)組:Arrays.stream(數(shù)組)或者使用Stream.of來創(chuàng)建
? ? ? ?Integer[] arr = {1,2,3,4,5};Stream<Integer> stream = Arrays.stream(arr);Stream<Integer> stream2 = Stream.of(arr);雙列集合:轉(zhuǎn)換成單列集合后再創(chuàng)建
? ? ? ?Map<String,Integer> map = new HashMap<>();map.put("蠟筆小新",19);map.put("黑子",17);map.put("日向翔陽",16); ?Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();3.4.2 中間操作
filter
可以對流中的元素進(jìn)行條件過濾,符合過濾條件的才能繼續(xù)留在流中。
例如:
打印所有姓名長度大于1的作家的姓名
? ? ? ?List<Author> authors = getAuthors();authors.stream().filter(author -> author.getName().length()>1).forEach(author -> System.out.println(author.getName()));map
可以把對流中的元素進(jìn)行計算或轉(zhuǎn)換。
例如:
打印所有作家的姓名
? ? ? ?List<Author> authors = getAuthors(); ?authors.stream().map(author -> author.getName()).forEach(name->System.out.println(name)); // ? ? ? 打印所有作家的姓名List<Author> authors = getAuthors(); ? // ? ? ? authors.stream() // ? ? ? ? ? ? ? .map(author -> author.getName()) // ? ? ? ? ? ? ? .forEach(s -> System.out.println(s)); ?authors.stream().map(author -> author.getAge()).map(age->age+10).forEach(age-> System.out.println(age));distinct
可以去除流中的重復(fù)元素。
例如:
打印所有作家的姓名,并且要求其中不能有重復(fù)元素。
? ? ? ?List<Author> authors = getAuthors();authors.stream().distinct().forEach(author -> System.out.println(author.getName()));注意:distinct方法是依賴Object的equals方法來判斷是否是相同對象的。所以需要注意重寫equals方法。
待更新
總結(jié)
以上是生活随笔為你收集整理的函数式编程-Stream流的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java函数式编程学习——Stream流
- 下一篇: Mac OS使用技巧之八:Dock栏使用