自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

這個(gè)類庫(kù)可以幫助你理解Java中的函數(shù)式編程

開發(fā) 后端
今天介紹一個(gè)函數(shù)式Java工具包,它表現(xiàn)了很多優(yōu)秀的函數(shù)式編程思想。以前介紹的熔斷降級(jí)組件Hystrix的替代品resilience4j就基于vavr庫(kù)。

[[405499]]

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

Vavr

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

可觀察的副作用

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

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

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

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

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

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

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

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

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

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

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

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

原始鏈表保持不變,新的鏈表大小保持不變?cè)乇惶鎿Q了。當(dāng)然你可以使用其它API來(lái)生成一個(gè)大小變化的副本,不過可以肯定的是原始的鏈表一定不會(huì)發(fā)生改變。

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

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

Vavr的一些特色

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

元組

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

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

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

Function

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

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

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

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

還有派生操作:

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

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

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

猜一猜答案是幾?

帶有特性的值容器

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

Option

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

Lazy

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

  1. Lazy<Double> 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ù)式編程語(yǔ)言大都支持模式匹配,同為JVM語(yǔ)言的Scala中就有這種特性,而Java目前是沒有的??梢杂行У貛椭覀儨p少if-else,舉個(gè)例子:

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

你就說吧,繞不繞?,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)為),對(duì)于習(xí)慣于傳統(tǒng)OOP編程的開發(fā)者來(lái)說確實(shí)不容易接受。你不妨從Vavr類庫(kù)入手去學(xué)習(xí)函數(shù)式編程的思想。今天介紹的只是它很少的一部分,還有更多等著你去發(fā)現(xiàn)、去借鑒。忘記說了,如果你想在項(xiàng)目中引用它,可以引入下面這個(gè)坐標(biāo):

  1. <!-- https://mvnrepository.com/artifact/io.vavr/vavr --> 
  2. <dependency> 
  3.     <groupId>io.vavr</groupId> 
  4.     <artifactId>vavr</artifactId> 
  5.     <version>0.10.3</version> 
  6. </dependency> 

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

 

責(zé)任編輯:武曉燕 來(lái)源: 碼農(nóng)小胖哥
相關(guān)推薦

2017-08-18 08:40:40

OpenStack建模數(shù)據(jù)中心

2010-06-22 13:32:26

函數(shù)式編程JavaScript

2024-12-05 10:37:36

Java純函數(shù)final

2024-09-29 15:35:23

2020-02-06 19:12:36

Java函數(shù)式編程編程語(yǔ)言

2012-12-27 09:49:21

Web響應(yīng)式

2023-10-07 00:01:02

Java函數(shù)

2024-02-28 08:37:28

Lambda表達(dá)式Java函數(shù)式接口

2018-11-15 10:20:59

Python函數(shù)式編程編程語(yǔ)言

2010-08-03 08:54:07

JDK 7Lambda表達(dá)式函數(shù)式編程

2022-10-08 14:26:09

開發(fā)Web工具

2010-03-11 17:46:29

Pythond類

2020-09-22 11:00:11

Java技術(shù)開發(fā)

2023-11-27 17:49:23

層次分析法算法

2020-09-23 07:50:45

Java函數(shù)式編程

2017-10-17 16:23:58

函數(shù)式編程ReduxReact

2023-02-19 15:20:19

2020-08-31 07:19:57

MonoFlux Reactor

2023-04-02 14:09:51

2024-02-26 08:32:04

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)