Java函数式编程

在很长的一段时间里,Java一直是面向对象的语言,一切皆对象,如果想要调用一个函数,函数必须属于一个类或对象,然后在使用类或对象进行调用。但是在其它的编程语言中,如js,c++,我们可以直接写一个函数,然后在需要的时候进行调用,即可以说是面向对象编程,也可以说是函数式编程。

从功能上来看,面向对象编程没什么不好的地方,但是从开发的角度来看,面向对象编程会多写很多可能是重复的代码行。比如创建一个Runnable的匿名类的时候:

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("do something...");
            }
        };

这一段代码中真正有用的只有run方法中的内容,剩余的部分都是属于Java编程语言的结构部分,没什么用,但是要写。

幸运的是Java8开始,引入了函数式编程接口与Lambda表达式,帮助我们写更少更优雅的代码

// 一行即可
Runnable runnable = () -> System.out.println("do something...");

函数式接口-Functional interfaces

一个接口类只有一个抽象的方法叫做函数式接口(Functional Interface),在JDK中大部分函数式接口都会标记上@FunctionalInterface注解,并不是所有的函数式接口都要写@FunctionalInterface注解,只是用来方便我们区分哪些是函数式接口的,当然如果标记了这个注解,内部有多个抽象方法的时候,会报编译错误。

Error:(3, 1) java: 意外的 @FunctionalInterface 注释
 xxx 不是函数接口
 在 接口 xxx 中找到多个非覆盖抽象方法

当一个类是函数式接口的时候,我们可以直接使用Lambda表达式来实例化它,而不用写很多模板式代码。

写法:

// 类名称  变量 = (参数) -> (函数体)
// 如
FunctionTest test = () -> { };

内置函数式接口

JDK中已经内置了一些标准的函数式接口,位于java.util.function包下,满足我们大多数情况下的需求。包下的接口都比较通用,如果我们想要写新的函数式接口,可以首先看这个包下是不是已经提供了。

那么这个包提供了那些接口呢?

  • 最常见的四种,Function,Consumer,Supplier,Predicate。标准输入输出,优雅代码所推荐的写法
    • Function:即一个入参一个出参的场景。
    • Consumer:一个入参,但是没有出参
    • Supplier:无入参,一个出参
    • Predicate:可以看做是特殊的Function,一个入参,出参为bool类型。
  • 两个入参的函数式接口,即两个入参,一个出参。BiFunction<T, U, R>, 最典型的使用案例即Java的Map方法。
    • BiFunction: 两个入参,一个泛型出参
    • ToDoubleBiFunction,ToIntBiFunction,ToLongBiFunction。两个入参,返回原始类型的出参
        HashMap<String, Object> map = new HashMap<>();
        map.put("a",1);
        map.put("b",2);
        map.replaceAll((o, o2) -> o + o2.toString());
        System.out.println(map.values())
  • 一元函数式接口, 可以看做是特殊的Function接口,入参与出参有相同的类型。UnaryOperator,相同类型的转换。

  • 原始类型Function,因为Java的原始类型或者叫做主类型,int,short,double之类的,不能作为泛型参数。官方对这些原始类型提供了特殊的函数式接口

    • 以int类型:IntFunction, IntComsumer,IntSupplieer, IntPredicate, IntToDoubleFcuntion, IntToLongFunction, IntUnaryOperator, ToIntFunction

官方:

https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

Lambda表达式

如果理解的了函数式接口,在一定程度上也是理解了Lambda表达式,Lambda表达式相当于对函数式接口的使用,我们不能只去写接口,但不去使用。

尽管Java支持了函数式接口,但是Java的函数仍然要寄托与类之中,不能单独存在,但是因为函数式接口只有一个抽象的函数,那么我们很明确的知道要使用拿一个方法。所以编译器可以自动帮我们推导要用哪个方法,不用在写多余的模板式代码:

Runnable runnable = () -> System.out.println("do something...");
  • 首先Runnable是一个函数式的接口,所以我们可以使用Lambda表达式来实例化它
  • 因为run方法没有参数,所以lambda表达式:(argument) -> {body},参数为空()
  • 关于函数体部分,如果我们只有一行代码可以省略掉{}。

除了函数调用的Lambda表达式,还有一些方法的引用操作,使用::,引用方法或者构造器而没有真正的实例化对象,可以探索下

String::toUpperCase
System.out::println
"abc"::length
ArrayList::new
int[]::new

官方:

https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html

https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

最后

Java的函数式编程远远超出这里所表达的内容,还需要更多的探索。当然这里主要介绍了Java的函数式接口,已经在java.util.function包下常见的函数式接口,最后对lambda表达式做了简单的说明。

参考地址:
http://tutorials.jenkov.com/java/lambda-expressions.html#method-references-as-lambdas
https://www.baeldung.com/java-8-lambda-expressions-tips
https://www.baeldung.com/java-8-functional-interfaces
https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容