精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Java中的七種函數式編程技巧

開發 前端
在Java中限制數據變異的方法并不多。然而,通過使用純函數,并明確避免數據變異和重新賦值(使用我們之前討論過的其他概念),可以實現這一目標。對于變量,我們可以使用final關鍵字,它是一個非訪問修飾符,用于防止通過重新賦值來改變變量的值。

環境:Java21

1. 簡介

函數式編程是一種編程范式,以函數為核心,避免改變狀態與可變數據,強調函數的第一公民地位。它通過使用高階函數和純函數,實現代碼的模塊化和重用性,提升可讀性和可維護性,常用于并發編程和數學計算等領域。

在函數式編程中,有兩條非常重要的規則:

  • 無數據變異
    這意味著一旦數據對象被創建后就不應該再被更改。任何對該對象的操作都應該返回一個新的對象,而不是修改原始對象。
  • 無隱式狀態
    應避免隱藏或隱式狀態。這樣理解:在傳統編程中,一個函數可能依賴于一些外部或隱藏的狀態,比如全局變量、靜態變量或者類成員變量等,這些狀態不是通過參數傳遞給函數的。在函數式編程中,提倡避免這種隱式的依賴關系,而是將所有需要的狀態都作為參數顯式地傳遞給函數。這樣做的結果是提高了代碼的透明度和可測試性,因為你清楚地知道函數依賴哪些輸入來產生輸出,同時也減少了副作用的發生,即函數執行時除了返回值外不改變其他任何東西。

除了上述內容外,還有以下可以在Java中應用的函數式編程概念:

  • 高階函數(Higher-order functions)
  • 閉包(Closures)
  • 柯里化(Currying)
  • 遞歸(Recursion)
  • 惰性求值(Lazy evaluations)
  • 引用透明性(Referential transparency)

使用函數式編程并不意味著必須全盤采用,你可以始終使用函數式編程概念來補充面向對象的概念,尤其是在Java中。無論你使用的范式或語言是什么,都可以盡可能地利用函數式編程的優點。

接下來,我們將詳細介紹函數式編程在Java中的應用

2. 實戰案例

2.1 一等函數和高階函數

在一等函數的上下文中,函數被視為頭等公民,意味著它們可以被賦值給變量、作為參數傳遞給其他函數、從函數中返回,以及包含在數據結構中。遺憾的是,Java并不完全支持這一特性,因此像閉包、柯里化和高階函數這樣的概念在Java中實現起來不如在其他語言中那么方便。

在Java中最接近一等函數的概念是Lambda表達式。此外,在java.util.function包下還有一些內置的函數式接口,如Function、Consumer、Predicate、Supplier等,可以用于函數式編程。

只有當一個函數接受一個或多個函數作為參數,或者返回另一個函數作為結果時,它才能被視為高階函數。在Java中,我們最接近高階函數的方式是使用Lambda表達式和內置的函數式接口。

public class Test {
  public static void main(String[] args) {
    var list = Arrays.asList("Orange", "Apple", "Banana", "Grape", "XPack", "AKF");


    var ret = calcLength(list, new FnFactory<String, Object>() {
      public Object execute(final String it) {
        return it.length();
      }
    });
    System.err.printf("Length: %s%n", ret);
  }


  static <T, S> ArrayList<S> calcLength(List<T> arr, FnFactory<T, S> fn) {
    var list = new ArrayList<S>();
    arr.forEach(t -> list.add(fn.execute(t)));
    return list;
  }


  @FunctionalInterface
  public interface FnFactory<T, S> {
    S execute(T it);
  }

輸出結果:

Length: [6, 5, 6, 5, 5, 3]

接下來,我們使用內置的Function接口和Lambda表達式語法來簡化上面的示例:

public class Test1 {
  public static void main(String[] args) {
    var list = Arrays.asList("Orange", "Apple", "Banana", "Grape", "XPack", "AKF") ;
    var ret = calcLength(list, it -> it.length()) ;
    System.err.printf("Length: %s%n", ret) ;
  }


  static <T, S> ArrayList<S> calcLength(List<T> arr, Function<T, S> fn) {
    var list = new ArrayList<S>() ;
    arr.forEach(t -> list.add(fn.apply(t))) ;
    return list ;
  }
}

使用這些概念加上Lambda表達式,我們可以像下面這樣編寫閉包和柯里化。

public class ClosureTest {
  Function<Integer, Integer> add(final int x) {
    Function<Integer, Integer> add(final int x) {
    // 普通寫法
//    var partial = new Function<Integer, Integer>() {
//      public Integer apply(Integer y) {
//        return x + y;
//      }
//    };
    // 使用Lambda表達式語法;注意這里不能使用var
    Function<Integer, Integer> partial = y -> x + y ;
    return partial;
  }
    return partial;
  }


  public static void main(String[] args) {
    ClosureTest closure = new ClosureTest();


    var c1 = closure.add(100) ;
    var c2 = closure.add(200) ;


    System.out.println(c1.apply(66));
    System.out.println(c2.apply(66));
  }
}

運行結果

166
266

以上是關于閉包的應用。

Java中也有許多內置的高階函數,如java.util.Collections#sort方法:

public static void main(String[] args) {
  var list = Arrays.asList("Apple", "Orange", "Banana", "Grape");


  Collections.sort(list, (String a, String b) -> {
    return a.compareTo(b);
  });


  System.err.printf("%s%n", list) ; 
}

Java Stream相關API中也提供了許多高階函數,比如forEach、map等。

2.2 純函數

函數式編程傾向于使用遞歸而不是循環。在Java中,這可以通過使用流API或編寫遞歸函數來實現。讓我們來看一個計算數字階乘的例子。還使用JMH對這些方法進行了基準測試,并在下方列出了每操作的納秒數。

在傳統的迭代方法中:

@State(Scope.Thread)
public class FactorialTest {
  // 我們要使用JMH進行測試,所以通過@Param定義入參
  @Param({"20"})
  private long num ;
  @Benchmark
  public long factorial() {
    long result = 1;
    for (; num > 0; num--) {
      result *= num;
    }
    return result;
  }


  public static void main(String[] args) throws Exception {
    Options options = new OptionsBuilder()
        .include(FactorialTest.class.getSimpleName())
        .forks(1)
        .build() ;
    new Runner(options).run() ;
  }
}

測試結果

Benchmark                (num)  Mode  Cnt  Score   Error  Units
FactorialTest.factorial     20  avgt    5  0.475 ± 0.013  ns/op

同樣的功能也可以使用遞歸來實現,如下所示,這在函數式編程中更為青睞。

@State(Scope.Thread)
public class FactorialTest2 {
  @Param({ "20" })
  private long num;


  @Benchmark
  public long factorialRec() {
    return factorial(num);
  }
  private long factorial(long n) {
    return n == 1 ? 1 : n * factorial(n - 1);
  }
  public static void main(String[] args) throws Exception {
    Options options = new OptionsBuilder()
        .include(FactorialTest2.class.getSimpleName())
        .forks(1)
        .build();
    new Runner(options).run();
  }
}

測試結果

Benchmark                    (num)  Mode  Cnt   Score   Error  Units
FactorialTest2.factorialRec     20  avgt    5  17.316 ± 0.792  ns/op

遞歸方法的缺點是,它通常會比迭代方法更慢(我們追求的優勢在于代碼的簡潔性和可讀性),并且由于每次函數調用都需要作為棧幀保存到堆棧中,可能會導致棧溢出錯誤。

我們還可以使用Stream進行遞歸調用

@Param({ "20" })
private long num;


@Benchmark
public long factorialRec() {
  return LongStream.rangeClosed(1, num)
      .reduce(1, (n1, n2) -> n1 * n2);
}

運行結果

Benchmark                    (num)  Mode  Cnt   Score   Error  Units
FactorialTest2.factorialRec     20  avgt    5  17.618 ± 1.414  ns/op

與遞歸算法差不多。

在編寫Java代碼時,考慮到可讀性和不可變性,可以考慮使用流API或遞歸;但如果性能至關重要,或者迭代次數將非常大,則應使用標準循環。

2.3 惰性求值(Lazy evaluations)

惰性求值(Lazy evaluation)或非嚴格求值是指推遲表達式的計算,直到其結果真正被需要時才進行計算。一般來說,Java執行的是嚴格求值,但對于像&&、||和?:這樣的運算符,它會進行惰性求值。我們可以利用這一點在編寫Java代碼時實現惰性求值。

考慮下面這個例子,在這個例子中Java會急切地(eagerly)計算所有內容:

public static void main(String[] args) {
  System.out.println(addOrMultiply(true, add(4), multiply(4))); // 8
  System.out.println(addOrMultiply(false, add(4), multiply(4))); // 16
}


public static int add(int x) {
  System.out.println("executing add");
  return x + x;
}


public static int multiply(int x) {
  System.out.println("executing multiply");
  return x * x;
}


public static int addOrMultiply(boolean add, int onAdd, int onMultiply) {
  return (add) ? onAdd : onMultiply;
}

執行結果

executing add
executing multiply
8
executing add
executing multiply
16

函數一早就被執行了。

我們可以使用Lambda表達式和高階函數將此重寫為惰性求值的版本:

public static void main(String[] args) {
  UnaryOperator<Integer> add = t -> {
    System.out.println("executing add");
    return t + t;
  };
  UnaryOperator<Integer> multiply = t -> {
    System.out.println("executing multiply");
    return t * t;
  };
  System.out.println(addOrMultiply(true, add, multiply, 4));
  System.out.println(addOrMultiply(false, add, multiply, 4));
}


public static <T, R> R addOrMultiply(
    boolean add, Function<T, R> onAdd, 
    Function<T, R> onMultiply, T t) {
  return (add ? onAdd.apply(t) : onMultiply.apply(t));
}

執行結果

executing add
8
executing multiply
16

我們可以看到只執行了所需的功能。

2.4 引用透明性(Referential transparency)

表示在程序中,一個函數調用可以用它的返回值來替換,而不改變程序的行為。換句話說,對于相同的輸入,函數總是產生相同的結果,沒有副作用。

遺憾的是,在Java中限制數據變異的方法并不多。然而,通過使用純函數,并明確避免數據變異和重新賦值(使用我們之前討論過的其他概念),可以實現這一目標。對于變量,我們可以使用final關鍵字,它是一個非訪問修飾符,用于防止通過重新賦值來改變變量的值。

例如,下面的代碼將在編譯時產生錯誤:

final var list = Arrays.asList("Apple", "Orange") ;
// 你不能重新賦值
list = Arrays.asList("Pack", "XXXOOO") ;

但是,當變量持有對其他對象的引用時,這并不會起到作用。例如,即使使用了final關鍵字,下面的對象變異仍然會發生:

final var list = new ArrayList<>() ;
// 我們還是可以添加數據
list.add("XXX") ;
list.add("OOO") ;

final 關鍵字允許引用變量的內部狀態被修改,因此從函數式編程的角度來看,final 關鍵字僅對常量和捕獲重新賦值有用。

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2021-10-19 14:51:33

說服力IT主管CIO

2011-02-22 16:09:53

Eclipse調試

2022-07-01 08:00:44

異步編程FutureTask

2015-09-02 12:12:13

2019-11-11 16:44:20

機器學習Python算法

2025-08-05 08:30:08

2025-05-13 08:20:58

2013-01-07 10:14:06

JavaJava枚舉

2020-01-14 08:00:00

.NET緩存編程語言

2022-05-10 08:08:01

find命令Linux

2025-02-10 08:43:31

Java異步編程

2022-03-14 07:40:14

RibbonSpringNacos

2022-07-25 10:15:29

垃圾收集器Java虛擬機

2025-01-21 08:00:00

限流微服務算法

2010-10-15 10:02:01

Mysql表類型

2025-05-12 10:00:00

JavaScript代碼編碼

2016-03-16 10:39:30

數據分析數據科學可視化

2023-02-14 08:32:41

Ribbon負載均衡

2019-09-06 09:00:00

開發技能代碼

2025-01-15 10:46:23

開發JavaScript集合
點贊
收藏

51CTO技術棧公眾號

国产夫妻在线播放| 国产成人久久精品77777综合 | 9191在线播放| 成人黄色一级视频| 国产精品精品久久久久久| 亚洲国产123| 日韩欧美ww| 欧美精品粉嫩高潮一区二区| 东北少妇不带套对白| 成人资源www网在线最新版| 国产一区视频导航| 欧洲亚洲妇女av| 日本妇女毛茸茸| 国产一区二区精品福利地址| 欧美成人女星排行榜| www.xxx亚洲| aa视频在线观看| 亚洲色图20p| 日韩国产精品一区二区三区| 草草视频在线播放| 蜜桃av一区二区在线观看| 91精品国产99| 久久精品www人人爽人人| 成人综合专区| 亚洲免费一在线| 亚洲国产欧美日韩在线| 99久久综合国产精品二区| 亚洲va中文字幕| 久久久无码中文字幕久...| 青青草免费在线| 成人性色生活片| 91在线精品播放| 中文字幕在线网址| 久久精品毛片| 4k岛国日韩精品**专区| 久草视频免费播放| 93在线视频精品免费观看| 亚洲免费一在线| 成人手机在线免费视频| 北条麻妃在线一区二区免费播放 | 污视频在线免费观看| 韩国v欧美v亚洲v日本v| 国产精品毛片a∨一区二区三区|国| 国产精品二区一区二区aⅴ| 亚洲乱码在线| 色yeye香蕉凹凸一区二区av| 扒开jk护士狂揉免费| 成人偷拍自拍| 日韩欧美中文一区| 中文字幕1区2区| 亚洲图色一区二区三区| 日韩一级高清毛片| 亚洲色图欧美自拍| 999精品视频在线观看| 欧美日韩www| 日本人69视频| 国产日本亚洲| 欧美一级淫片007| 亚洲欧美日韩一二三区| 成人久久精品| 欧美一卡2卡三卡4卡5免费| 99国产精品免费视频| av综合网页| 亚洲精品www久久久| 国产伦精品一区二区三区妓女| 欧美18免费视频| 亚洲加勒比久久88色综合| 影音先锋黄色资源| 久久99国产精品视频| 一区三区二区视频| 国产传媒免费在线观看| 欧美福利影院| 91国语精品自产拍在线观看性色 | 美女视频黄久久| 91精品国产综合久久男男| 国产露脸91国语对白| 国产一区二区中文字幕| 国产精品免费视频一区二区| 无码国产精品一区二区免费16| 久久久噜噜噜久久中文字幕色伊伊| 欧美精品久久| 日本电影在线观看网站| 一级女性全黄久久生活片免费| 欧美狂野激情性xxxx在线观| 色一区二区三区| 欧美视频一区二区在线观看| 亚洲男人天堂2021| 欧美重口另类| 久久精品2019中文字幕| 国产在线视频你懂的| 国产伦理一区| 国产一区二区丝袜高跟鞋图片| 亚洲第一大网站| 久久久五月婷婷| 先锋影音男人资源| 亚洲wwww| 精品日产卡一卡二卡麻豆| 白白色免费视频| 一区二区三区在线观看免费| 国产91av在线| av中文字幕播放| 日本55丰满熟妇厨房伦| 欧美极品在线观看| 欧美成人午夜剧场免费观看| 制服.丝袜.亚洲.中文.综合懂色| 看国产成人h片视频| 狠狠色伊人亚洲综合网站色| av资源种子在线观看| 亚洲电影第三页| 一区二区三区欧美精品| 婷婷激情久久| 欧美肥臀大乳一区二区免费视频| 狠狠狠狠狠狠狠| www.欧美日韩国产在线| 亚洲综合第一| 最新欧美电影| 亚洲精品按摩视频| 久久国产免费观看| 国产在线视频一区二区| 视频一区不卡| 欧美男男激情videos| 日韩欧美国产综合在线一区二区三区| 久久婷婷五月综合| 香蕉av777xxx色综合一区| 亚洲一区二区三区sesese| 国产精品久久久久久久龚玥菲| 亚洲国产va精品久久久不卡综合| 亚洲xxx在线观看| 国产成人精品免费视| 2018国产精品视频| 黑人精品一区二区三区| 亚洲免费毛片网站| 久久精品影视大全| 国产亚洲一区| 热re99久久精品国产66热| 日本黄色免费视频| 一区二区三区在线观看视频| 天天干天天色天天干| 国语产色综合| 国产脚交av在线一区二区| 头脑特工队2免费完整版在线观看| 一区二区激情视频| 精品人妻一区二区乱码| 国产精品多人| 国产精品免费区二区三区观看| 色呦呦在线视频| 日韩欧美你懂的| 婷婷伊人五月天| 激情五月婷婷综合网| 中文精品一区二区三区| 日韩大陆av| 久久亚洲成人精品| 精品久久在线观看| 亚洲激情在线激情| 一区二区三区四区影院| 在线一区免费| 亚洲一区二区三区毛片 | 午夜精品美女自拍福到在线| 亚洲免费一级片| 午夜欧美视频在线观看| 久久一区二区电影| 天堂久久一区二区三区| 先锋影音亚洲资源| 日本.亚洲电影| www.国产精品一二区| 国产精品怡红院| 亚洲国产一区二区视频| 特级西西人体4444xxxx| 久久精品成人| www.午夜色| 成人线上播放| 日韩美女毛茸茸| 日本三级视频在线观看| 日韩欧美不卡一区| 亚洲午夜18毛片在线看| 中文字幕国产一区二区| 久久久久亚洲av无码麻豆| 欧美人与禽猛交乱配视频| 韩国成人一区| 日韩不卡视频在线观看| 萌白酱国产一区二区| 日韩一卡二卡在线| 欧美又粗又大又爽| 免费一级片在线观看| 久久婷婷一区二区三区| 成人亚洲免费视频| 一本色道久久综合一区| 亚洲成人自拍视频| www.丝袜精品| 国产精品久久久久9999| 呦呦在线视频| 一本一道久久a久久精品逆3p| 国产免费无遮挡| 欧美日韩一区二区在线 | 国产欧亚日韩视频| segui88久久综合| 中文字幕亚洲一区二区三区五十路 | 日本不卡中文字幕| 2014国产精品| 一区二区三区短视频| 久久久精品在线| 国产精品国产高清国产| 欧美精品日韩综合在线| 成人免费区一区二区三区| 亚洲欧洲精品一区二区三区 | 国产亚洲亚洲国产一二区| 欧美亚洲国产视频小说| 成人在线观看亚洲| 亚洲欧洲激情在线| 狠狠人妻久久久久久综合麻豆| 91国在线观看| 男女视频免费看| 一区二区三区在线免费观看| 日本不卡一区视频| 久久先锋影音av| 男男一级淫片免费播放| 国产精品亚洲成人| www.com污| 日韩电影在线观看电影| 91视频最新入口| 亚洲三级免费| www.夜夜爱| 欧美在线亚洲综合一区| 亚洲最新在线| 精品国产乱码| 欧美日韩亚洲在线| 人人精品亚洲| 国产一区免费| aaa国产精品| 99视频国产精品免费观看| 91成人福利社区| 国产精品永久免费| 成人全视频免费观看在线看| 55夜色66夜色国产精品视频| 国产盗摄——sm在线视频| 久久久久久久爱| 四季久久免费一区二区三区四区| 日韩专区中文字幕| 日本福利在线| x99av成人免费| 黄色av电影在线观看| 日韩有码在线视频| 免费在线观看黄| 日韩中文在线不卡| 免费高清在线观看| 久久久国产精彩视频美女艺术照福利| 尤物视频在线免费观看| 日韩中文字幕网站| 高清免费电影在线观看| 欧美猛男性生活免费| 日本在线观看大片免费视频| 久热精品在线视频| 在线观看av免费| 韩剧1988免费观看全集| 成人免费图片免费观看| 日本精品性网站在线观看| 3d欧美精品动漫xxxx无尽| 国产精品91在线观看| 91成人在线| 91免费的视频在线播放| 综合激情久久| 精品国产一区二区三区久久久久久| 久久中文资源| 欧洲一区二区日韩在线视频观看免费| 久久综合影院| 国产日本欧美在线| 亚洲黄色影片| 亚洲性生活网站| 激情综合色播激情啊| 亚洲婷婷在线观看| 久久亚洲综合av| 91视频最新网址| 亚洲一区二区三区在线| wwwxxx亚洲| 欧美日韩一区在线| av免费在线观看不卡| 亚洲国产精品va在线| 国产在线一二| 九九热r在线视频精品| 在线男人天堂| 国产深夜精品福利| 久久激情av| 亚洲欧美成人一区| 在线看片日韩| 9久久婷婷国产综合精品性色 | 国产一区美女| 国产av无码专区亚洲精品| 久久国产综合精品| 逼特逼视频在线观看| 国产欧美综合在线| 久草福利资源在线观看| 在线观看成人免费视频| jizz中国女人| 国产亚洲精品激情久久| 日本片在线看| 国产欧美日韩91| 欧美三级自拍| 日本精品福利视频| 日韩激情视频网站| 欧美双性人妖o0| 国产精品国产a| 中文字幕一区二区人妻电影| 91麻豆精品国产91| 国产二区视频在线观看| 久久久亚洲精品视频| 青青在线精品| 欧美日韩国产免费一区二区三区| 欧美一区国产在线| 天天操天天爽天天射| www..com久久爱| 色欲人妻综合网| 欧美日韩中文国产| 青青草免费在线视频| 久久久久国产精品www| 日韩久久一区| 日韩区国产区| 性伦欧美刺激片在线观看| 潘金莲一级淫片aaaaa| 国产精品久久久久久久午夜片| 伊人手机在线视频| 亚洲国产日韩欧美在线图片| 成人在线视频亚洲| 91精品久久久久久久久| 精品视频网站| 国产一级不卡毛片| 91在线你懂得| 日韩成人在线免费视频| 欧美大片一区二区| 50度灰在线| 92国产精品视频| 天天做天天爱天天综合网2021| 男人女人黄一级| 久久精品一级爱片| 在线观看国产亚洲| 亚洲精品短视频| 狠狠躁少妇一区二区三区| 国产精品麻豆免费版| 亚洲视频观看| 久久久久久婷婷| 亚洲成人免费视频| 人妻精品无码一区二区| 欧美激情国内偷拍| 国产一级成人av| 少妇人妻无码专区视频| k8久久久一区二区三区| 国产在线观看99| 亚洲高清一区二| 中文在线免费二区三区| 欧美精品123| 蜜臀av一区二区三区| 91大神福利视频| 在线成人免费视频| 26uuu亚洲电影在线观看| 亚洲一区亚洲二区亚洲三区| 欧美二区视频| 亚洲国产综合视频| 一本大道久久a久久综合| 国产高清视频在线| 国产精品一二区| 中文字幕免费精品| 免费看91视频| 精品久久久久久久久久久久久久| 三级av在线| 国产精品露脸自拍| 欧美暴力喷水在线| 国产亚洲无码精品| 欧美亚洲国产一区在线观看网站| 天堂аⅴ在线地址8| 91精品国产一区二区三区动漫| 伊人久久亚洲影院| 一道本在线观看| 69av一区二区三区| 岛国av在线播放| 婷婷久久伊人| 国产精品888| 日本特级黄色片| 色多多国产成人永久免费网站 | 蜜桃臀一区二区三区| 日韩成人免费电影| 久久久久久久久久久97| 亚洲精品中文字幕av| 亚洲色图综合| 99热自拍偷拍| 一区在线观看视频| 深夜福利视频一区| 成人久久久久久| 国产色综合网| 久久久久久久久久97| 亚洲精品国产欧美| 亚洲综合伊人| 国产主播在线看| 亚洲激情图片qvod| 国产精品99999| 福利视频一区二区三区| 日韩黄色片在线观看| 久久精品女人毛片国产| 中文字幕不卡在线视频极品| 99精品中文字幕在线不卡 | 中文字幕日韩精品在线| 国产精品qvod|