Java函數式編程神器 VAVR
點擊上方藍色字體,選擇“標星公眾號”
優(yōu)質文章,第一時間送達

什么是函數式編程
1、基本概念:他是一種編程范式,對于函數式編程來說,它只關心定義輸入數據和輸出數據相關的關系,數學表達式里面其實是在做一種映射(mapping),輸入的數據和輸出的數據關系是什么樣的,是用函數來定義的。
2、特征:
(1)stateless:函數不維護任何狀態(tài)。函數式編程的核心精神是 stateless,簡而言之就是它不能存在狀態(tài),打個比方,你給我數據我處理完扔出來。里面的數據是不變的。
(2)immutable:輸入數據是不能動的,動了輸入數據就有危險,所以要返回新的數據集。(不可變的)
Java為什么要函數式編程
3、優(yōu)勢
(1)沒有狀態(tài)就沒有傷害。
(2)并行執(zhí)行無傷害。
(3)Copy-Paste 重構代碼無傷害。
(4)函數的執(zhí)行沒有順序上的問題。
問題所在
函數式相對于普通的java變成來說,如果沒有用過就會直接不清楚這個函數是干什么的,這個是干什么的,如果在團隊中只有部分人使用,那我們在其他人在理解我們的代碼上就會有問題,也就回增加學習成本,和開發(fā)成本。
使用的問題:問題排查的問題 和異常的捕獲的問題。
EXAMPLE
package Vavr;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sun.istack.internal.FragmentContentHandler;
import io.vavr.CheckedFunction0;
import io.vavr.Function1;
import io.vavr.Function2;
import io.vavr.Function3;
import io.vavr.Lazy;
import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.control.Either;
import io.vavr.control.Option;
import io.vavr.control.Try;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Generated;
import lombok.Getter;
/**
* 函數式編程demo
*
* @author yuanxindong
* @date 4/17/21 7:30 PM
*/
public class VavrTest {
/**
* 元組的使用
*/
public static void tupleTest() {
//of 靜態(tài)方法支持使用
Tuple2<String, Integer> tuple2 = Tuple.of("Hello", 100);
Tuple2<String, Integer> updatedTuple2 = tuple2.map(String::toUpperCase, v -> v * 5);
String result = updatedTuple2.apply((str, number) -> String.join(", ",
str, number.toString()));
System.out.println(result);
}
/**
* function函數的使用
*/
public static void functionTest() {
// 函數定義,前3個是入參,最后是R
Function3<Integer, Integer, Integer, Integer> function3 = (v1, v2, v3) -> (v1 + v2) * v3;
// 函數的組合
Function3<Integer, Integer, Integer, Integer> composed =
function3.andThen(v -> v * 100);
//執(zhí)行結果
int result = composed.apply(1, 2, 3);
System.out.println(result);
//還有包含部分函數的應用
Function1<Integer, Integer> function1 = function3.apply(1, 2);
Integer apply = function1.apply(1);
System.out.println(apply);
//項目聯(lián)想
//結合項目場景使用比如說PDT中定義幾個 函數比如:計算MP時效的函數,計算ALG的函數時效,在定義一些函數結果的拼接等
}
/**
* 柯里化想要解決的問題: 柯里化方法的使用 柯里化的含義: 柯里化(currying)是與λ演算相關的重要概念。通過柯里化,可以把有多個輸入的函數轉換成只有一個輸入的函數,從而可以在λ演算中來表示。 柯里化的名稱來源于數學家 Haskell Curry。Haskell Curry 是一位傳奇性的人物,以他的名字命令了 3 種編程語言,Haskell、Brook 和 Curry。
* 柯里化是把有多個輸入參數的求值過程,轉換成多個只包含一個參數的函數的求值過程。 對于清單 6 的函數 f(a, b, c),在柯里化之后轉換成函數 g,則對應的調用方式是 g(a)(b)(c)。 函數 (x, y) -> x + y 經過柯里化之后的結果是 x -> (y -> x + y)。
*/
public static void curriedTest() {
//設置函數 v1 v
Function3<Integer, Integer, Integer, Integer> function3 = (v1, v2, v3) -> (v1 + v2) * v3;
//可以看出來是返回來了一個函數
Function1<Integer, Function1<Integer, Integer>> apply = function3.curried().apply(1);
//多次柯里化后就會返回我們想要的記過
int result = function3.curried().apply(1).curried().apply(2).curried().apply(3);
System.out.println(result);
}
/**
* 記憶化方法 會將之前計算過的方法進行存儲,相同參數在第二次調用的時候會使用緩存
*/
public static void memoized() {
//計算差方
Function2<BigInteger, Integer, BigInteger> pow = BigInteger::pow;
//記憶化
Function2<BigInteger, Integer, BigInteger> memoized = pow.memoized();
long start = System.currentTimeMillis();
memoized.apply(BigInteger.valueOf(1024), 1024);
long end1 = System.currentTimeMillis();
memoized.apply(BigInteger.valueOf(1024), 1024);
long end2 = System.currentTimeMillis();
System.out.printf("%d ms -> %d ms", end1 - start, end2 - end1);
}
/**
* java 8 中的optional 是類似 其目的都是為了避免NPE的出現(xiàn)
*/
public static void optionTest() {
//個人覺得option好用的地方在于這個of 靜態(tài)函數。
Option<String> str = Option.of("Hello");
str.map(String::length);
//使用對應的值
Option<Integer> integers = str.flatMap(v -> Option.of(v.length()));
boolean empty = integers.isEmpty();
System.out.println(integers);
}
/**
* either 的使用 包含兩個值,left(異常值) 和 right(正確值)
*/
public static void eitherAndTryTest() {
//這個是
Either<String, String> either =
compute()
.map(str -> str + " World")
.mapLeft(Throwable::getMessage);
System.out.println(either);
//Try的使用,不用寫過多的catch,左后將left值交給某一個函數統(tǒng)一處理,
//在pdt中有很多這樣的代碼,try catch 嵌套起來使用 包含參數定義的參數校驗異常
//
Fruit.fromColor("1111");
}
private static ThreadLocalRandom random = ThreadLocalRandom.current();
private static Either<Throwable, String> compute() {
return random.nextBoolean()
? Either.left(new RuntimeException("Boom!"))
: Either.right("Hello");
}
@Getter
public enum Fruit {
APPLE("APPLE", "BLACK"),
BANANA("BANANA", "BLUE"),
NONE("ORANGE", "WHITE");
private final String name;
private final String color;
Fruit(String name, String color) {
this.name = name;
this.color = color;
}
public static Fruit fromColor(String color) {
return Try.of(() -> Arrays.stream(Fruit.values())
.filter(t -> t.getColor().equals(color))
.findFirst().orElse(NONE))
.toEither().getOrElse(NONE);
}
}
/**
* Lazy 表示的是一個延遲計算的值。在第一次訪問時才會進行求值操作,而且該值只會計算一次。之后的訪問操作獲取的是緩存的值。Lazy.of 從接口 Supplier 中創(chuàng)建 Lazy 對象。方法 isEvaluated 可以判斷 Lazy 對象是否已經被求值。
*/
public static void LazyTest() {
Lazy<BigInteger> lazy = Lazy.of(() ->
BigInteger.valueOf(1024).pow(1024));
System.out.println(lazy.isEvaluated());
System.out.println(lazy.get());
System.out.println(lazy.isEvaluated());
System.out.println(lazy.get());
System.out.println(lazy.isEvaluated());
Lazy<BigInteger> lazy2 = Lazy.of(() ->
BigInteger.valueOf(1024).pow(1024));
System.out.println(lazy2.isEvaluated());
System.out.println(lazy2.get());
//未想到應用場景
}
public static void main(String[] args) {
tupleTest();
functionTest();
curriedTest();
memoized();
LazyTest();
}
}
————————————————
版權聲明:本文為CSDN博主「Jeff、yuan」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權協(xié)議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:
https://blog.csdn.net/weixin_40413961/article/details/115803185
粉絲福利:Java從入門到入土學習路線圖
??????

??長按上方微信二維碼 2 秒
感謝點贊支持下哈 
評論
圖片
表情
