大概一年多之前,我對java8的理解還僅限一些只言片語的文章之上,后來出于對函數式編程的興趣,買了本參考書看了一遍,然后放在了書架上,后來,當我接手大客戶應用的開發工作之后,java8的一些工具,對我的效率有了不小的提升,因此想記錄一下java"8的一些常用場景,我希望這會成為一個小字典,能讓我免于頻繁翻書,但是總能找到自己想找的知識。
用于舉例的model:
@Data public class Apple { private Long appleId; private String appleName; private Float appleWeight; private Integer appleClassic; }一、Java 8 Lambda 表達式
這無疑是最常用的功能之一,其實lambda表達式的作用,應該就是簡潔明了,實際上是用最短的字符,通過類型推導,語法糖等方式去對編譯器描述清楚這段代碼的功能,這和泛型有點相似,對于編程人員來說,一定程度上也提高了編程效率和代碼可讀性。
如常用的lambda表達式:
process(()->System.out.println("this is so cool!"))
例如對蘋果重量排序:
Listapples = Lists.newArrayList(); for (int i = 1; i < 10; i++) { Apple apple = new Apple(); apples.add(apple); } apples.sort(Comparator.comparing(Apple::getAppleWeight)); 反序: apples.sort(Comparator.comparing(Apple::getAppleWeight).reversed()); 重量相同時:比較等級: apples.sort(Comparator .comparing(Apple::getAppleWeight) .reversed() 謂詞復合查詢: Predicate a = apple -> apple.getAppleWeight() > 10; weight10.or(apple -> apple.getAppleClassic() > 2) .and(apple -> StringUtils.equalsIgnoreCase(apple.getAppleName(), "優質蘋果")); 可以看做(a||b)&&c 函數復合: Function f = a -> a.getAppleWeight() + 1; Function g = a -> a * 2; Function h = f.andThen(g); 數學寫作 h=g(f(x)) Function g = a -> a.getAppleWeight() + 1; Function f = a -> a * 2; Function h = f.compose(g); 數學寫作 h=f(g(x))
小結:java8實際上想傳遞函數,函數是什么?是一個映射,可以看做x->y,輸入x然后映射到值y的過程,
java無法擺脫一切皆是對象的思想,因此函數式依附在對象上傳遞的,因此也有了下面的說法,方法引用,以及函數式接口,讓函數隨著對象傳遞,為了函數式編程,甚至專門寫一個接口---對象來傳遞函數。然而,函數才是主角。
方法引用十分簡單,其實也是將方法作為參數傳遞。使用::域作用符,將一段方法傳遞。
舉例:Apple::getAppleId
String::subString System.out::println三、Java 8 函數式接口 函數式編程
利用java進行函數式編程主要就是利用函數式接口,但是函數式接口在java8之前就有一些了,就例如多線程的runnable,但是8以前是沒有lambda表達式的,所以只能使用匿名內部類,在用過lambda表達式的人看來,那是相當臃腫的,8更新了lambda表達式,這就使函數式編程更上一層樓.
java8的函數式接口為我們傳遞函數提供了工具,我們可以自己定義函數式接口,然后讓其他人,或者是java API調用。
關于函數接口,需要記住的就是兩件事:
函數接口是行為的抽象;
函數接口是數據轉換器。
在我接觸到java8流式處理的時候,我的第一感覺是流式處理讓集合操作變得簡潔了許多,通常我們需要多行代碼才能完成的操作,借助于流式處理可以在一行中實現。其本質是,將一些原本開發者需要做的處理如迭代等,放在了java庫里,讓我們只關心自己的業務邏輯,比如我們希望對一個包含整數的集合中篩選出所有的偶數,并將其封裝成為一個新的List返回,那么在java8之前,我們需要通過如下代碼實現:
過去: Listevens = new ArrayList<>(); for (final Integer num : nums) { if (num % 2 == 0) { evens.add(num); } } stream實現: List evens = nums.stream().filter(num -> num % 2 == 0).collect(Collectors.toList()); 我們需要取出10個等級高于3的蘋果,跳過其中兩個,按重量排序,去重,然后取出蘋果的Name,然后取出名字的每個字符: List appleName = apples.parallelStream() .filter(a -> a.getAppleClassic() < 2) .sorted(Comparator.comparing(Apple::getAppleWeight)) .map(Apple::getAppleName) .map(s -> s.split("")) .limit(10) .skip(2) .distinct() .flatMap(Arrays::stream) .collect(Collectors.toList()); 構造AppleId ApppleName Map: Map appleIdMap = apples.stream() .collect(Collectors.toMap(Apple::getAppleId, Apple::getAppleName, (s, s2) -> s.length() > s2.length() ? s : s2)); 謂詞查找: if (appleName.stream().anyMatch(a -> StringUtils.equalsIgnoreCase(a, "一級蘋果"))); if (appleName.stream().allMatch(a -> StringUtils.equalsIgnoreCase(a, "一級蘋果"))); if (appleName.stream().noneMatch(a -> StringUtils.equalsIgnoreCase(a, "一級蘋果"))); 短路查找: appleName.stream() .filter(a -> StringUtils.equalsIgnoreCase(a, "一級蘋果")) .findAny() .ifPresent(System.out::println); findfirst在并行時限制多一些,如果不在意返回的是哪個元素,使用findAny。 求和: apples.stream() .map(Apple::getAppleWeight) .reduce(0F, (a, b) -> a + b); 計數: apples.stream().count();
使用stream的好處:
1.更簡潔,更易讀
2.可復合,更靈活
3.可并行
Optional著重為解決java的NPE問題是Java8提供的為了解決null安全問題的一個API。善用Optional可以使我們代碼中很多繁瑣、丑陋的設計變得十分優雅。
使用Optional,我們就可以把下面這樣的代碼進行改寫: public static String getName(User u) { if (u == null) return "Unknown"; return u.name; } 不過,千萬不要改寫成這副樣子。 public static String getName(User u) { Optionaluser = Optional.ofNullable(u); if (!user.isPresent()) return "Unknown"; return user.get().name; } 這樣才是正確使用Optional的姿勢。那么按照這種思路,我們可以安心的進行鏈式調用,而不是一層層判斷了。 public static String getName(User u) { return Optional.ofNullable(u) .map(user->user.name) .orElse("Unknown"); } 看一段代碼: public static String getChampionName(Competition comp) throws IllegalArgumentException { if (comp != null) { CompResult result = comp.getResult(); if (result != null) { User champion = result.getChampion(); if (champion != null) { return champion.getName(); } } } throw new IllegalArgumentException("The value of param comp isn"t available."); } 讓我們看看經過Optional加持過后,這些代碼會變成什么樣子。 public static String getChampionName(Competition comp) throws IllegalArgumentException { return Optional.ofNullable(comp) .map(c->c.getResult()) .map(r->r.getChampion()) .map(u->u.getName()) .orElseThrow(()->new IllegalArgumentException("The value of param comp isn"t available.")); } 還有很多不錯的使用姿勢,比如為空則不打印可以這么寫: string.ifPresent(System.out::println);
參考資料:《Java 8 in Action: Lambdas, streams, and functional-style programming》 Raoul-gabriel Urma (作者), Mario Fusco (作者), Alan Mycroft (作者)
作者:文爍
點擊 閱讀更多 查看更多詳情
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/73147.html
摘要:依舊使用剛剛對蘋果排序的代碼?,F在,要做的是篩選出所有的綠蘋果,也許你會這一個這樣的方法在之前,基本上都是這樣寫的,看起來也沒什么毛病。但是,現在又要篩選一下重量超過克的蘋果。 《Java8實戰》-讀書筆記第一章(01) 最近一直想寫點什么東西,卻不知該怎么寫,所以就寫寫關于看《Java8實戰》的筆記吧。 第一章內容較多,因此打算分幾篇文章來寫。 為什么要關心Java8 自1996年J...
摘要:并發教程原子變量和原文譯者飛龍協議歡迎閱讀我的多線程編程系列教程的第三部分。如果你能夠在多線程中同時且安全地執行某個操作,而不需要關鍵字或上一章中的鎖,那么這個操作就是原子的。當多線程的更新比讀取更頻繁時,這個類通常比原子數值類性能更好。 Java 8 并發教程:原子變量和 ConcurrentMap 原文:Java 8 Concurrency Tutorial: Synchroni...
摘要:使用解決的數據流問題原文譯者飛龍協議在年三月發布,距離現在年三月五號快有一年了。除了,最實用的特性是新的數據流。是吧,注是瀏覽器上的數據流的接口,并解決了上述問題。 使用Intellij IDEA 解決Java8的數據流問題 原文:Fixing Java 8 Stream Gotchas with IntelliJ IDEA 譯者:飛龍 協議:CC BY-NC-SA 4.0 ...
摘要:示例字符串數值算術和文件原文譯者飛龍協議大量的教程和文章都涉及到中最重要的改變,例如表達式和函數式數據流。不僅僅是字符串,正則表達式模式串也能受益于數據流。 Java 8 API 示例:字符串、數值、算術和文件 原文:Java 8 API by Example: Strings, Numbers, Math and Files 譯者:飛龍 協議:CC BY-NC-SA 4.0 ...
摘要:哪吒社區技能樹打卡打卡貼函數式接口簡介領域優質創作者哪吒公眾號作者架構師奮斗者掃描主頁左側二維碼,加入群聊,一起學習一起進步歡迎點贊收藏留言前情提要無意間聽到領導們的談話,現在公司的現狀是碼農太多,但能獨立帶隊的人太少,簡而言之,不缺干 ? 哪吒社區Java技能樹打卡?【打卡貼 day2...
閱讀 2335·2021-11-22 14:56
閱讀 1471·2021-09-24 09:47
閱讀 909·2019-08-26 18:37
閱讀 2829·2019-08-26 12:10
閱讀 1527·2019-08-26 11:55
閱讀 3147·2019-08-23 18:07
閱讀 2304·2019-08-23 14:08
閱讀 610·2019-08-23 12:12