日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
這個(gè)類庫可以幫助你理解Java中的函數(shù)式編程

每當(dāng)JDK發(fā)布了新版本就有同學(xué)說“你發(fā)任你發(fā),我用Java 8”,可在工作中有不少人依然不太擅長使用Java8的新特性,而這些特性往往讓Java不再“臃腫”。不過我個(gè)人認(rèn)為Java8所有的新特性中最具有代表性的一定是函數(shù)式編程。有人會說這種風(fēng)格太抽象難懂了,當(dāng)你熟練掌握這種設(shè)定之后,你一定會感到很香。慢慢地你也會領(lǐng)會到函數(shù)式編程的魅力和精髓。今天介紹一個(gè)函數(shù)式Java工具包,它表現(xiàn)了很多優(yōu)秀的函數(shù)式編程思想。以前介紹的熔斷降級組件Hystrix的替代品resilience4j就基于vavr庫。

Vavr

Vavr是一個(gè)Java8函數(shù)庫,它運(yùn)用了大量的函數(shù)式編程范式。創(chuàng)造性地封裝了一些持久性的數(shù)據(jù)結(jié)構(gòu)和函數(shù)式控制結(jié)構(gòu)。而且從中可以學(xué)到很多有用的編程思想。

可觀察的副作用

我們的代碼中經(jīng)常會出現(xiàn)一些看不見的陷阱,從代碼語義中這些陷阱是無法被觀察的。例如

 
 
 
 
  1. int divide(int a, int b){
  2.  return a/b;
  3. }

我們知道a/b會得到一個(gè)整數(shù),但是卻不能從代碼上明確地知道如果b=0將會拋出java.lang.ArithmeticException異常;而如果是a+b則不會帶來任何副作用。所以我們需要讓這種副作用是可觀察的。對于這一點(diǎn)Vavr做出了一種設(shè)計(jì):

 
 
 
 
  1. Try divide(Integer a, Integer b) {
  2.     return Try.of(() -> a / b);
  3. }

將可能的副作用封裝到一個(gè)容器中,明確了可能的失敗,當(dāng)你看到返回的是Try 時(shí),就意味著結(jié)果可能“并不順利”,以便于針對性地進(jìn)行預(yù)防。

不可變的數(shù)據(jù)結(jié)構(gòu)

很多語言都在使用不可變的數(shù)據(jù)結(jié)構(gòu),比如Golang、Kotlin。主要原因是不可變的值:

  • 本質(zhì)上是線程安全的,因此不需要同步
  • 對于equals和hashCode是可靠的
  • 不需要克隆
  • 在非受檢unchecked類型轉(zhuǎn)換中是類型安全的
  • 對于函數(shù)式編程來說不可變值是最透明的

為此Vavr設(shè)計(jì)了一個(gè)集合類庫,旨在代替Java中的集合框架。Vavr 的集合庫包含一組豐富的函數(shù)式數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)建立在 lambdas 之上。它們與 Java 原始集合共享的唯一接口是Iterable。這些數(shù)據(jù)結(jié)構(gòu)是持久性的,一旦初始化本身就不可改變,你可以使用一些操作來返回更改后的副本。例如經(jīng)典的數(shù)據(jù)結(jié)構(gòu)單向鏈表:

 
 
 
 
  1. // 1   2  3
  2. List source = List.of(1, 2, 3);

如果我們將一個(gè)新元素0放在原始鏈表尾部的前面

 
 
 
 
  1. //  0  2  3
  2. List newHeadList = source.tail().prepend(0);
  3. //  1  2  3
  4. System.out.println(source);

原始鏈表保持不變,新的鏈表大小保持不變元素被替換了。當(dāng)然你可以使用其它API來生成一個(gè)大小變化的副本,不過可以肯定的是原始的鏈表一定不會發(fā)生改變。

 
 
 
 
  1. // 0 1 2 3
  2. List prepend = source.prepend(0);
  3. // 1 2 3 0
  4. List append = source.append(0);

這只是其中的一部分編程思想,接下來我將介紹Vavr的一些特色。

Vavr的一些特色

Vavr提供了一些非常有用的而且有特色的API。

元組

熟悉Python的同學(xué)對元組(Tuple)一定不陌生。元組將固定數(shù)量的元素組合在一起,以便它們可以作為一個(gè)整體傳遞。與數(shù)組或列表不同,元組可以包含不同類型的對象,但它也是不可變的。目前Vavr提供了最多8個(gè)元素的元組結(jié)構(gòu)。

 
 
 
 
  1. // (felord.cn, 22)
  2. Tuple2 java8 = Tuple.of("felord.cn", 22); 
  3. // felord.cn
  4. String s = java8._1; 
  5. // 22
  6. Integer i = java8._2;

這個(gè)可以用來模擬Java中不具有的多返回值的特性。

Function

Java本身提供了Function接口,但是Vavr則提供了更加豐富的Function擴(kuò)展,例如可以組合多個(gè)Function

 
 
 
 
  1. Function1 multiplyByTwo = a -> a * 2;
  2. Function1 compose = multiplyByTwo.compose(a -> a + 1);
  3. // 6
  4. Integer apply = compose.apply(2);

除此之外,還可以讓潛在的副作用降級(lift),有點(diǎn)類似于微服務(wù)的熔斷,以避免在函數(shù)執(zhí)行中處理異常

 
 
 
 
  1. Function2 divide = (a, b) -> a / b;
  2. // 降級 
  3. Function2> safeDivide = Function2.lift(divide);
  4. // 返回一個(gè)加強(qiáng)版的Optional
  5. Option apply = safeDivide.apply(1, 0);
  6. boolean empty = apply.isEmpty();
  7. // true
  8. System.out.println(empty);

還有派生操作:

 
 
 
 
  1. Function2 divide = (a, b) -> a / b;
  2. Function1 a = divide.apply(4);
  3. Integer apply = a.apply(2);

這有點(diǎn)類似于柯里化,當(dāng)我們用到更多入?yún)r(shí)柯里化才更加明顯:

 
 
 
 
  1. Function3 sum = (a, b, c) -> a + b + c;
  2. final Function1> add2 = sum.curried().apply(1);
  3. Integer apply = add2.apply(2).apply(3);

猜一猜答案是幾?

帶有特性的值容器

這個(gè)不太好用中文說明,有一些值帶有獨(dú)特的性質(zhì),比如開頭提到的Try,用來顯式表明可能遇到異常。Vavr提供了很多具有獨(dú)特性質(zhì)的值容器。

Option

類似Optional,但是比Optional更加強(qiáng)大。

Lazy

Lazy是一個(gè)惰性計(jì)算的容器,表示當(dāng)使用時(shí)才去計(jì)算且只計(jì)算一次。

 
 
 
 
  1. Lazy lazy = Lazy.of(Math::random);
  2. lazy.isEvaluated(); // = false
  3. lazy.get();         // = 0.123  
  4. lazy.isEvaluated(); // = true
  5. lazy.get();         // = 0.123 
  6. // 需要使用數(shù)據(jù)時(shí)才從數(shù)據(jù)源加載
  7. Data lazyData = Lazy.val(DataSourceService::get, Data.class);

其它還有一些非常有用的容器,你可以嘗試它們。

模式匹配

函數(shù)式編程語言大都支持模式匹配,同為JVM語言的Scala中就有這種特性,而Java目前是沒有的??梢杂行У貛椭覀儨p少if-else,舉個(gè)例子:

 
 
 
 
  1. public static String convert(int input) {
  2.       String output;
  3.       if (input == 1) {
  4.           output = "one";
  5.       } else if (input == 2) {
  6.           output = "two";
  7.       } else if (input == 3) {
  8.           output = "three";
  9.       } else {
  10.           output = "unknown";
  11.       }
  12.       return output;
  13.   }

你就說吧,繞不繞?,Vavr就清爽多了。

 
 
 
 
  1. public static String vavrMatch(int input) {
  2.      return Match(input).of(
  3.              Case($(1), "one"),
  4.              Case($(2), "two"),
  5.              Case($(3), "three"),
  6.              Case($(), "unknown")
  7.      );
  8.  }

當(dāng)然還有其它一些玩法需要你自己去發(fā)現(xiàn)。

總結(jié)

函數(shù)式編程作為Java8最大的一個(gè)亮點(diǎn)(個(gè)人認(rèn)為),對于習(xí)慣于傳統(tǒng)OOP編程的開發(fā)者來說確實(shí)不容易接受。你不妨從Vavr類庫入手去學(xué)習(xí)函數(shù)式編程的思想。今天介紹的只是它很少的一部分,還有更多等著你去發(fā)現(xiàn)、去借鑒。忘記說了,如果你想在項(xiàng)目中引用它,可以引入下面這個(gè)坐標(biāo):

 
 
 
 
  1.     io.vavr
  2.     vavr
  3.     0.10.3

本文轉(zhuǎn)載自微信公眾號「 碼農(nóng)小胖哥」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系碼農(nóng)小胖哥公眾號。


本文標(biāo)題:這個(gè)類庫可以幫助你理解Java中的函數(shù)式編程
文章分享:http://www.dlmjj.cn/article/cdppdje.html