首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Coding
V2EX  ›  Java

Java8 的函数式编程支持,我学习后觉得很沮丧和鸡肋

  •  
  •   zazalu · 63 天前 · 5346 次点击
    这是一个创建于 63 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不知道是我问题还是什么,就感觉怪怪的

    72 回复  |  直到 2019-10-12 15:56:47 +08:00
        1
    xlui   63 天前
    您好,是你的问题,看一看没有函数式支持之前的代码就知道这东西解决了什么了。
        2
    oneisall8955   63 天前 via Android   ♥ 1
    function 包用起来还是美滋滋的,将方法封装成对象,支持 lambda 表达式,用习惯了就改不回来了
        3
    qping   63 天前   ♥ 2
    给你举个应用场景:
    有个 list 想提取一部分字段转成一个 List<String>
    ```
    List<TableInfo> tables = ...;
    List<String> tableNames = ...;
    for(TableInfo table : tables){
    String tableName = table.getName().toUpperCase();
    tableNames.add(tableName);
    }
    ```

    使用 lamda,只要一行:
    ```
    List<String> tableNames = tables.stream().map(v -> v.getTableName().toUpperCase()).collect(Collectors.toList());
    ```

    香不香
        4
    fuyufjh   63 天前
    要么___,要么___,scala 欢迎你
        5
    fuyufjh   63 天前
    @qping 这明明是使用了 stream api
        6
    godlovesxcjtest   63 天前
    @fuyufjh 但是这也是函数式编程啊
        7
    fuyufjh   63 天前
    @godlovesxcjtest 您对 FP 可能有误解
        8
    zhuangzhuang1988   63 天前   ♥ 1
    @qping 不香, 代码没减多少, 而且更难看懂了,调试也不好,性能还不咋的.
        9
    hbsfxlz   63 天前
    @zhuangzhuang1988 难看懂的说明没有认真去了解过,stream 的可读性比 for 循环可读性强了一百倍
        10
    chendy   63 天前
    最常用的场景可能就是 StreamAPI 了
    还好 idea 已经有 stream debugger 了,否则 debug 真的痛苦…
        11
    godlovesxcjtest   63 天前 via Android
    @fuyufjh 求指教。
        12
    taotaodaddy   63 天前 via Android
    java 的 fp 实现堪称是见过的颇不优雅
        13
    FireFoxAhri   63 天前 via Android
    你需要 scala
        14
    Senventise   63 天前 via Android
    @taotaodaddy 你这句子有语病啊
        15
    coldear   63 天前
    kotlin 吧
        16
    zazalu   63 天前
    @qping 这些简单的还能接受,确实简化了,主要是受不了那个 andThen()函数里产生函数的写法,觉得不是很直观
        17
    zazalu   63 天前
    ```java
    import java.util.function.*;

    class I {
    @Override
    public String toString() { return "I"; }
    }

    class O {
    @Override
    public String toString() { return "O"; }
    }

    public class TransformFunction {
    static Function<I,O> transform(Function<I,O> in) {
    return in.andThen(o -> {
    System.out.println(o);
    return o;
    });
    }
    public static void main(String[] args) {
    Function<I,O> f2 = transform(i -> {
    System.out.println(i);
    return new O();
    });
    O o = f2.apply(new I());
    }
    }
    ```

    这个既有趣又感觉我玩的是 java 吗?
        18
    araaaa   63 天前
    去用异步框架 vert.x 之类的
        19
    Jrue0011   63 天前
    @zazalu lambda 挺好用的,如果你觉得一段方法链用了很多个 lambda 太长的话,可以定义把这些方法抽出来定义成静态方法或者成员方法,通过方法引用传递
        20
    qping   63 天前
    @zhuangzhuang1988 #8 兄弟,你可以尝试用一下,一点也不复杂,当你了解后可读性并不差。最初我也是很抵制的,stream api 可以代替很多恶心的 for 循环的场景,用的飞起


    @zazalu #16 从代码的可读性来说还是 Function 接口是有点复杂,这些接口更像是给底层架构设计使用的。有的东西只需要了解,然后能读懂其他人的代码就可以了,日常你可以不用嘛。
        21
    soeur   63 天前 via Android
    我觉得挺好用的呀
        22
    Jrue0011   63 天前
    大概是这样,手写没有编译器警告可能会有错误。。但是是能实现的

    import java.util.function.*;

    class I {
    @Override
    public String toString() { return "I"; }

    public O println() {
    System.out.println(this);
    return new O();
    }
    }

    class O {
    @Override
    public String toString() { return "O"; }

    public O println() {
    System.out.println(this);
    return this;
    }
    }

    public class TransformFunction {
    static Function<I,O> transform(Function<I,O> in) {
    return in.andThen(O::println);
    }

    public static void main(String[] args) {
    Function<I,O> f2 = transform(I::println);
    O o = f2.apply(new I());
    }
    }
        23
    LeeSeoung   63 天前
    技术每天都在更新,不是你能挑三拣四的时候,今天还在为掌握了这些而满足的时候,明天就有一个更高效的技术就替代它了,一生都需要学习。
        24
    zzxop   63 天前
    建议你再看一下,了解了之后肯定不想再用以前的方法
        25
    guolaopi   63 天前
    我一直以为 java 跟 C#一样老早就支持这么写了(一脸懵逼
        26
    buckbuckgo   63 天前
    我自己是熟悉的功能性接口(比如 Runnable, OnClickListener)用 lambda 很简洁, 自己也清楚, 不熟悉不常用的仍旧用 匿名对象
        27
    zazalu   63 天前
    @zzxop 嗯,在看,新手第一次接触 Java 的 FP
        28
    zazalu   63 天前
    @guolaopi java8 挺早的了!只不过我参与的项目开始用 8 版本是最近的事情 orz,之前一直 1.7
        29
    softtwilight   63 天前
    刚开始不熟悉正常的,大脑比较讨厌改变,多用用就能感受到好了,函数编程最主要的是对思维模式的影响,你对问题的抽象完全不一样了
        30
    Aresxue   63 天前
    性能稍差点,但是可读性上升了很多,前提是你习惯函数式编程的思维,毕竟面向对象的编程其实和人类思维的代沟还是差蛮多的
        31
    kansyoukyou   63 天前
    从 Java7 一路写过来的,觉得 Stream 和 FP 结合还是很好用的
        32
    Kamiyu0087   63 天前
    函数式编程真的大大提高代码可读性
    真心建议啃下来,其实一点不难的
        33
    djFFFFF   63 天前
    之前接触过 Python 或者 Scala 的话,沮丧是很正常的。Java 8 的实现一点都不优雅。没接触的话,应该是你还没从 oop 的思路转过来。
        34
    djFFFFF   63 天前
    补充一下 @qping 的例子:

    Python 版:
    `[t.getTableName() for t in tables]`

    Scala 版:
    `tables.map(_.getTableName())`
        35
    lihongjie0209   63 天前
    @djFFFFF #34 scala 版本可以使用 vavr 实现。

    python 版本的是列表解析, 不上常规意义上的 map。
        36
    djFFFFF   63 天前
    @lihongjie0209 嗯,python 这个是语法糖,不是函数式编程。vavr 看了下感觉还是很笨重
        37
    feelinglucky   63 天前
    建议啃下来,真的
        38
    Orenoid   63 天前
    @djFFFFF #34 python 不是也有 map filter reduce 吗
        39
    lazyfighter   63 天前
    我把他称之为,写着舒服看着难受,至于上面的 demo,都是太简单了,你见过上百行的 stream 处理吗,各种类型转换看着头都大了
        40
    by73   63 天前
    是很鸡肋,连 pattern matching 都没有(逃
        41
    dk7952638   63 天前
    lambda 很优雅很装逼,但你看过他的实现方式之后你就会发现性能堪忧,想优雅还是直接 scala 吧,java 就不是干这事的
        42
    Narcissu5   63 天前
    lambda 好不好,请去看下 lambda 之前无数的匿名类
        43
    taotaodaddy   63 天前 via Android
    java 的 fp 实现堪称是见过的颇不优雅
    @Senventise 还真是。。。我重说

    java 的 fp 实现实在是不优雅呢
        44
    ipwx   62 天前
    去看看 Vert.x 吧。

    函数式对 CRUD 确实可能没啥用。但是对很多高级编程范式,还是很有用的。
        45
    ipwx   62 天前
    @lazyfighter 上百行的 stream,写成普通形式不是要上千,不还是一样不容易懂。

    这种长长长的 stream 不该合理地分块、拆句子、加注释么?

    当然如果你说大部分 Java 程序员写不出容易看懂的 stream,那你的逻辑就和 go 语言那帮拥簇一样了:既然用不好,就砍掉呗(手动斜眼)。我反正不喜欢这样的哲学,我更喜欢 Scala 和 C++ 那种,菜全都端上来了,吃那些,自己看着办。
        46
    optional   62 天前
    java lambda 最恶心的是 checked exception
        47
    zazalu   62 天前
    @optional 和这个有什么关系吗?
        48
    yukongzz   62 天前
    可以看看 kotlin
        49
    optional   62 天前
    @zazalu 大部分 fp interface 都不带 throw
        50
    sevenstone   62 天前
    Scala 欢迎你
        51
    zazalu   62 天前
    @optional 嗯,但是这个自己实现一个不就好了吗(擦汗)
        52
    lazyfighter   62 天前
    @ipwx stream 拆开写就不舒服了啊, 本来就是一个句子但是拆开了人为使他易读写着就不舒服了,所以我把它定位为写着爽读着累。另外我的观点是这样的,好比我写代码的时候不写注释,我看代码的时候骂别人不写注释,啊哈哈哈哈哈哈
        53
    aguesuka   62 天前 via Android
    @zazalu stream 只接受 jdk 的接口作为参数,而且 function 的 default 方法写不写都不好
        54
    slanternsw   62 天前
    函数式不好 x
    java 的函数式不好 √
        55
    uleh   62 天前
    作为一个从 JDK 1.4 用过来的 java 程序员,表示 lambda 真香……
        56
    Cstone   62 天前
    函数式真的很香,没了函数式,没法用流没法链式操作,整个代码都会变得丑陋不堪
        57
    mrobot   62 天前 via iPhone
    个人项目 上上上上真香
    团队项目 确实很怪 最好别写花里胡哨的代码 保重大家都看的懂能跑起来就行 减少沟通成本
        58
    djFFFFF   62 天前
    @Orenoid 有但是用的不多,list comprehension 是被认为更 pythonic (可以理解为更有情怀)的方式
        59
    CononYc   62 天前
    一开始我也是这么认为的,函数式看着头大,后面了解多了之后就感觉真香,真好用
        60
    hitsmaxft   62 天前   ♥ 1
    只是从 api 上改善了对 lambda 支持而已。别提什么函数式。这么去看就释然了。

    1. 支持 lambda 写法的匿名接口实现,不用显示写匿名类实现。(仅限于单个实现方法的接口,多个方法就嗝屁了)
    2. 提供 function 包,这样子第三方有了公共的 api,大伙都可以快乐地玩高阶函数了,不用动不动一堆类。
    3. stream api 改善一些并发和列表处理的延迟计算的实现,基于 1,可以大大减少代码量

    只是提供了函数式的 api/语法糖 ,参考了函数式的一些优点。
        61
    irgil   62 天前
    这位亲亲你好,是你的问题呦
        62
    wupher   62 天前
    你这要是玩 ReactiveX 还不得吐?

    不过,我现在也更习惯 Groovy 和 Kotlin 风格的 lambda。

    Java 8 的能接受,自己写的时候会绕一下。
        63
    zazalu   62 天前
    @hitsmaxft 到位,我看下来也觉得是这么回事
        64
    haosamax   62 天前
    @qping 我觉得看起来挺爽的,比 for 明朗多了。看不懂的,是不了解 stream 吧
        65
    islandev   62 天前
    function 可以作为参数了 可以传递了 怎么好玩的
    可以精简代码
    ```java
    private Function<T, String> funca;

    private List<Function<T>> funcb

    private String name;

    ```
        66
    bozhongshao   62 天前
    @qping 习惯简单不出错的转换 用 lambda 但是很复杂的还是习惯用大括号括住, 慢慢来。
        67
    andyholo   62 天前 via Android
    函数式和面向对象不是对立的吧?怎么听你们说的好像两者有个地位高低似的,复杂逻辑我是不敢用函数式,太复杂耦合度太高了
        68
    kingfalse   62 天前 via Android
    kotlin 吧,spring boot 支持的很好
        69
    wzdbsss   62 天前 via iPhone
    怎么实现 stream 里面的 if else ?最近用 reactor,不知道怎么优雅的 if else
        70
    mskf   62 天前
    函数式编程咯,并行运算只需要 parallelStream 就行了
        72
    fuyufjh   61 天前
    @godlovesxcjtest 我不知道怎么解释,所以仅仅列出事实:FP 的代表语言 Haskell/Scheme 并不支持类似 Stream API 的东西,而 Stream API 的集大成者 ReactiveX 支持几乎所有语言
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3361 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 40ms · UTC 05:01 · PVG 13:01 · LAX 21:01 · JFK 00:01
    ♥ Do have faith in what you're doing.