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

lambda 表达式大家在工作中用的多么,小白看了好多遍也理解不住

  •  
  •   wuwudeqi · 57 天前 · 7068 次点击
    这是一个创建于 57 天前的主题,其中的信息可能已经有所发展或是发生改变。
    91 回复  |  直到 2019-12-03 09:03:03 +08:00
    donglan1995
        1
    donglan1995   57 天前
    lewinlan
        2
    lewinlan   57 天前
    Pandas 常用。
    ```python
    df.apply(lambda x: str(x) if isinstance(x, Datetime) else x)
    ```
    等效于
    ```python
    def the_function(x):
    if isinstance(x, Datetime):
    return str(x)
    return x
    ```
    kkkkkrua
        3
    kkkkkrua   57 天前
    wuwudeqi
        4
    wuwudeqi   57 天前
    那来看得一定要学会了😢
    hdbzsgm
        5
    hdbzsgm   57 天前   ♥ 3
    自己瞎玩除外, 不推荐在任何场景下使用 lambda
    wuwukai007
        6
    wuwukai007   57 天前
    不是 java 主题吗?
    zifangsky
        7
    zifangsky   57 天前
    多,经常用
    zifangsky
        8
    zifangsky   57 天前
    你可以看一下《 Java 8 实战》的相关章节,然后自己再多练习一些比较复杂的写法,然后差不多就可以了
    ghouleztt
        9
    ghouleztt   57 天前 via iPhone
    非常多
    kran
        10
    kran   57 天前 via Android
    把 lambda 想象成一个类的实例,这个类有个 apply 方法,方法体和 lambda 的内容等价。当调用这个 lambda 时,相当于 obj.apply(),这些实例化啦,调用转换啦,都是编译器帮你做了。
    是不是好理解一点
    mixure
        11
    mixure   57 天前
    lambda {p %{没看懂 1 楼的代码,x 对象 也是可调用么?} }.call
    cco
        12
    cco   57 天前
    经常用,多写写 scala。。。
    wysnylc
        13
    wysnylc   57 天前
    @hdbzsgm #5 ?????????????????????????????????????
    lagoon
        14
    lagoon   57 天前
    我也理解不了。不过常见的 IDE 自动填补了。
    lambda 也是趋势了吧。不单是 java。
    许多新语言,都推荐这么写。
    wysnylc
        15
    wysnylc   57 天前   ♥ 1
    marcong95
        16
    marcong95   57 天前
    前端表示用得不亦乐乎,问题是你哪里理解不了呢?

    其实就是个匿名函数,不知道是不是 Java 包装过度产生了一些理解难度,你可以考虑从别的语言角度去理解
    wc951
        17
    wc951   57 天前 via Android
    别挣扎了,你不用新框架里大把的在用
    @hdbzsgm
    aguesuka
        18
    aguesuka   57 天前   ♥ 1
    lambda 表达式优于匿名类
    方法引用优于 lambda 表达式
    effective java 是这么说的
    SuperMari0
        19
    SuperMari0   57 天前
    其实用的多了你会发现这东西超级顺手
    jdgui
        20
    jdgui   57 天前
    挺多的。。
    但是我都是用 IDE 自动补齐的。
    aragakiyuii
        21
    aragakiyuii   57 天前
    不用 lambda 的话要死了
    http://objcoding.com/2019/03/04/lambda/
    avalon0624
        22
    avalon0624   57 天前
    常用,举个例子 ,创建一个临时 Timer 来重试失败的业务
    tgich
        23
    tgich   57 天前   ♥ 1
    用的太多了,基本每次要在集合里搞花样都得用,不用就活不了了
    rockyou12
        24
    rockyou12   57 天前
    天天都在大量使用……特别是各种处理、过滤数据……
    imycc
        25
    imycc   57 天前
    python 经常用。其他语言的不了解。

    如果 lambda 的逻辑太复杂,就写成局部的函数或者类方法了
    nulIptr
        26
    nulIptr   57 天前
    c++ c# ts 系程序员震惊了,没有 lambda 也能写代码? java 是最近才有的吗?
    ipwx
        27
    ipwx   57 天前
    楼主是不是不能理解 “闭包” ?其他地方 Lambda 表达式和一个普通函数有啥区别。。。

    闭包的话,楼主你就假想一下写了个匿名类,成员变量是所有当前作用域能看到的变量,然后初始化就是把变量给了它一份那种。。。
    passerbytiny
        28
    passerbytiny   57 天前   ♥ 1
    lambda 表达式没那么难,就这一点:他是一个函数,完整书写形式是 (arg1, arg2, arg3, ....) -> {//函数体},在一些特定场合,有一些简写形式。

    对于 Java 中的 lambda 表达式,再加几点:
    一个 lambda,对应一个匿名内部类;
    这个匿名内部类实现的接口,必须是函数式接口——只有一个非默认方法的接口,而 lambda 表达式所表示的函数,就是用来实现这个方法的;
    Java 有一些特定的简写形式。

    完了,剩下的实践中积累经验就行。
    Raymon111111
        29
    Raymon111111   57 天前
    多用就顺手
    wdv2ly
        30
    wdv2ly   57 天前 via Android
    csharp 表示没 lambda 的代码就没有灵魂
    ala2008
        31
    ala2008   57 天前
    经常用,很方便,特别是数据处理
    lux182
        32
    lux182   57 天前
    lambda
    是什么
    lambda 是一个代码块,但是是一个极简的代码块,它表示一个函数,实现一种功能。相比函数,lambda 省略了函数名、参数类型、返回类型,甚至是花括号。

    为什么用 lambda
    因为 lambda 函数比较简洁,另外 lambda 可以作为参数,直接传递给函数

    怎么用 lambda
    Python 中定义,

    m = lambda x:x*2
    print m(2)
    可以看出 lambda 赋值给变量(函数名),并通过函数名加参数调用

    java 中的 lambda
    Java 中的 lambda 是一种不完全的实现。在 Java 8 里面,lambda 的类型(申明的变量)都是一个函数式接口(被注解为 @FunctionInterface 的接口),其本身也就是接口的实现。
    hannhuan
        33
    hannhuan   57 天前
    ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄两个月前刚工作时看代码也是一头雾水。然后经历了太多
    ```
    if(x != cond1) {bla;}
    else {bla}
    ```
    后就爱上了 lambda……用着真的好爽啊!
    l93814690
        34
    l93814690   57 天前 via iPhone
    @hannhuan 这个用 lambda 后是怎样的
    luckylo
        35
    luckylo   57 天前 via Android
    spring5.0 最低要求都 8 了。
    catqi
        36
    catqi   57 天前
    csharp 07 年 3.0 发布的时候就有 lambda 了
    araaaa
        37
    araaaa   57 天前 via iPhone
    去写 stream function reactive,写多了自然就会
    EricFuture
        38
    EricFuture   57 天前
    必须呀,可以用少写很多代码,就是要花一段时间熟悉
    TaAmSf
        39
    TaAmSf   57 天前
    Qt 中使用匿名函数很爽的。
    wleexi
        40
    wleexi   57 天前
    多的。已经是趋势了。
    winterbells
        41
    winterbells   57 天前
    经常用,很简单啊
    alt + enter [:doge]
    hantsy
        42
    hantsy   57 天前
    val filter = {age: Int -> age >30}
    AlisaDestiny
        43
    AlisaDestiny   57 天前
    用,可以简化代码,并且使代码更直观。
    hantsy
        44
    hantsy   57 天前
    作为 Java 8 特性,lambda 已经出来 5,6 年了吧。你还能以**太新了**为理由拒绝吗?

    第一次用的时候,一个项目要上 Java 8 (刚出来不久),要用 Spring Integration 和 Java 8 特性,那时 Spring Integration 4 有一个专门 Java 8 module(现在集成到 core 了), Spring 官方 Blog 有一个介绍 Spring Integration Java 8 DSL。

    https://spring.io/blog/2014/11/25/spring-integration-java-dsl-line-by-line-tutorial

    能够理解这个 Orders Bean 就差不多了。

    @Bean
    public IntegrationFlow orders() { // 12
    return f -> f // 13
    .split(Order.class, Order::getItems) // 14
    .channel(c -> c.executor(Executors.newCachedThreadPool()))// 15
    .<OrderItem, Boolean>route(OrderItem::isIced, mapping -> mapping // 16
    .subFlowMapping("true", sf -> sf // 17
    .channel(c -> c.queue(10)) // 18
    .publishSubscribeChannel(c -> c // 19
    .subscribe(s -> // 20
    s.handle(m -> sleepUninterruptibly(1, TimeUnit.SECONDS)))// 21
    .subscribe(sub -> sub // 22
    .<OrderItem, String>transform(item ->
    Thread.currentThread().getName()
    + " prepared cold drink #"
    + this.coldDrinkCounter.incrementAndGet()
    + " for order #" + item.getOrderNumber()
    + ": " + item) // 23
    .handle(m -> System.out.println(m.getPayload())))))// 24
    .subFlowMapping("false", sf -> sf // 25
    .channel(c -> c.queue(10))
    .publishSubscribeChannel(c -> c
    .subscribe(s ->
    s.handle(m -> sleepUninterruptibly(5, TimeUnit.SECONDS)))// 26
    .subscribe(sub -> sub
    .<OrderItem, String>transform(item ->
    Thread.currentThread().getName()
    + " prepared hot drink #"
    + this.hotDrinkCounter.incrementAndGet()
    + " for order #" + item.getOrderNumber()
    + ": " + item)
    .handle(m -> System.out.println(m.getPayload()))))))
    .<OrderItem, Drink>transform(orderItem ->
    new Drink(orderItem.getOrderNumber(),
    orderItem.getDrinkType(),
    orderItem.isIced(),
    orderItem.getShots())) // 27
    .aggregate(aggregator -> aggregator // 28
    .outputProcessor(group -> // 29
    new Delivery(group.getMessages()
    .stream()
    .map(message -> (Drink) message.getPayload())
    .collect(Collectors.toList()))) // 30
    .correlationStrategy(m ->
    ((Drink) m.getPayload()).getOrderNumber()), null) // 31
    .handle(CharacterStreamWritingMessageHandler.stdout()); // 32
    }

    }
    hannhuan
        45
    hannhuan   57 天前
    @l93814690
    // 原来的代码
    for (Sample s : samples){
    if (sample.getValue() == aValue){
    System.out.println(sample);
    }
    }

    // 然后...
    samples.stream()
    .filter(sample -> sample.getValue() == aValue)
    .forEach(System.out::println);

    // 或者...
    List<Sample> sortSampleByIndex = samples.stream()
    .sorted((s1, s2) -> s1.getIndex()- s2.getIndex())
    .collect(Collectors.toList());


    简化下之前写的大概是这样吧_(:з」∠)_ 不过我超菜,这个也不一定是正确的用法
    laminux29
        46
    laminux29   57 天前
    在 C#中,给学生数组,按照总分、语文分数、其他分数等字段进行多字段排序,自己写的话会有一堆 for 循环以及后处理,而 lambda 只需要一行:

    学生数组.OrderBy(x => x.总分).ThenBy(x => x.语文分数).ThenBy....

    这玩意本质是函数语言,和 SQL 的思路很像。如果你熟悉 SQL,你就会发现这玩意在处理数据时,非常好用。
    KentY
        47
    KentY   57 天前
    @hannhuan 想一下, 如果你在 for 里的调用, 比如那个 out.print(), 如果是另一个会 throw checked exception method, 要怎么处理?
    hantsy
        48
    hantsy   57 天前   ♥ 1
    @hannhuan
    .sorted((s1, s2) -> s1.getIndex()- s2.getIndex()) 可以用 Comparator.comparing, 如

    .sorted(comparing(Sample::getIndex)

    抽取,可以在 Sample 定义

    static Comparator<Sample> COMPARAED_BY_INDEX=comparing(Sample::getIndex );

    应用
    .sorted(COMPARAED_BY_INDEX)
    aliveyang
        49
    aliveyang   57 天前
    用 idea 自动补全, 然后就习惯写了
    sagaxu
        50
    sagaxu   57 天前 via Android
    最近一年基本没写过 for 循环,你说用的多不多
    hantsy
        51
    hantsy   57 天前
    @KentY 所有的流式( Stream,Future,ReactiveStreams )处理都有异常路径的,让你处理异常。
    rimutuyuan
        52
    rimutuyuan   57 天前
    完全不用!因为 go 根本没有
    KentY
        53
    KentY   57 天前
    @hantsy "异常路径" 是什么? google 没找到对应英语.
    缺省的是无法将 exception forward 到外面的. 需要自己 wrap 或者扩展 Consumer, Function 等.
    希望我们俩说的是一件事. :D
    hannhuan
        55
    hannhuan   57 天前
    @hantsy 学到了,感谢~下次试试。
    hantsy
        56
    hantsy   57 天前
    @KentY 留了一个 Exception 路径的入口,怎么优雅处理倒是一个问题,Stackoverflow 很多这种问题。
    ztcaoll222
        57
    ztcaoll222   57 天前
    记住: 2014 年出的 java 1.8
    KentY
        58
    KentY   57 天前
    @hantsy 你的例子是 CompletionStage interface 定义的方法而已. 跟我说的不是一个事. 或许我没表述清, ok:
    class Whatever{...
    public void foo throw WhateverException(){...}
    }

    in some method:
    ...someMethod(Collection<Whatever> collection) throw WhateverException{....
    collection.stream().foreach(Whatever::foo); --> here it won't work, the checked exception won't be forwarded to the caller method.
    }

    我是这个意思
    KentY
        59
    KentY   57 天前
    请忽视 syntax mistakes. like throws, (), etc.
    KentY
        60
    KentY   57 天前
    @hantsy
    "留了一个 Exception 路径的入口" 我不理解这句话. 什么是"路径"? 什么又是"入口"?

    另, 我在 SO 也相对活跃. 我不是不知道怎么解决来这求解决方案的. 只是, 看到人们说到 lambda 都是这些 foreach 啊, filter 啊, stream 啊, 没人提到在传统的 for -> stream()这个变换中, 不是所有都可以简单的改写的, 有些情况需要做特殊处理. 仅此而已.
    classyk
        61
    classyk   57 天前
    基本上把 lambda 当成就是一个回调函数的语法糖,是不是就好理解多了
    KentY
        62
    KentY   57 天前
    @classyk 我觉得 java 的 lambda 跟传统意义的 回调函数类似, 但本质还不一样. 回调函数是函数的一个地址, 而 java 的 lambda 其实是某些 interface 的实现. 本质是预先的 interface 实现或者匿名类. 其实地址都是那些 objects .. 在这些方面, java 不如某些比如 python, (C 就更不用说了)灵活.
    hantsy
        63
    hantsy   57 天前
    @KentY 嗯。我不觉得用 Lambda 仅仅是简写了代码,只是多一种编程方式的选择而已,没有什么东西是万能的。像之前提到用 Spring Integration Flow,有时在不好处理(还有测试的方便),一个长的 Flow 代码还是分成几段(用多个 Flow 拼接)。
    Revenant
        64
    Revenant   57 天前
    this.axios('/api/getData')
    .then( res => {
    console.log(res)
    }).catch( err => {
    console.log(err)
    })
    KentY
        65
    KentY   57 天前
    @hantsy 其实 compact 的代码, 调试起来成本大些. 比如说, fluent api design 是个好东西, 可是我 review 过 40 多行的.foo().bar()一直下来的代码. 我想, 当时这个开发人员, 写的时候, 心里应该是充满得意的, 因为他在用 fluent api 而且是"on the right track" 但是这样, 在调试的时候成本就加大, 另外, 这样一个 method 恨不得所有事情都给做里面, 因为它"可以"做. 也违背了功能单一化的原则...
    还有个例子就是, 看 camel 的东西就觉得那不是在 programming.... :-D
    yt1523102
        66
    yt1523102   57 天前
    java , 记住 stream 就可以了,流式子操作,可以转 map list
    turi
        67
    turi   57 天前
    c++ 不使用 感觉在用 c++98
    charlie21
        68
    charlie21   57 天前
    用个 lambda 就爽起来了?爽点也太低了罢
    billlee
        69
    billlee   57 天前
    这个要配合 immutable 数据结构和函数式编程。比如写 spark 不用 lambda 就会非常难受了
    FerrisChan
        70
    FerrisChan   57 天前
    C 艹,写 qt 就经常用
    MouCai
        71
    MouCai   57 天前 via Android
    我在 JS 里面,Lambda 就没停下来过
    Perry
        72
    Perry   57 天前
    5 楼什么鬼,JavaScript 里面用 Lambda 写 JSX 香的不行
    tianshilei1992
        73
    tianshilei1992   56 天前
    我写作业还用了 Lambda 表达式😂
    ```C++
    call_once(init_socket_once, [&]() {
    timeval to;
    to.tv_sec = 10;
    to.tv_usec = 0;

    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to));
    });
    ```
    dangyuluo
        74
    dangyuluo   56 天前
    反正在 C++ 14 里面用的很多,因为真的很方便啊。
    aaronysj
        75
    aaronysj   56 天前 via iPhone
    真香!
    factoid
        76
    factoid   56 天前 via iPhone
    @lewinlan 我不太明白为什么不能直接
    ```python
    df.apply(str(x) if isinstance(x, Datetime) else 1)”””
    changdy
        77
    changdy   56 天前
    用的不多..
    因为 已经把语言从 java 切换成了 kotlin
    wbing
        78
    wbing   56 天前 via iPhone
    写 c++和 kotlin 时常用,特别爽
    zunceng
        79
    zunceng   56 天前
    因为我懒
    不用 lambda 就得用高阶函数 ;不用高阶函数 就得用设计模式
    daimiaopeng
        80
    daimiaopeng   56 天前
    c++ 回调函数用 lambda ....
    JCZ2MkKb5S8ZX9pq
        81
    JCZ2MkKb5S8ZX9pq   56 天前
    @lewinlan 你这个情况好像不写 lambda 也行吧?
    a if condition else b 这个简写就可以吧。

    另外我一般 sorted 的时候是常用到,从字典深处取出或者计算个排序条件。
    inorilzy
        82
    inorilzy   56 天前
    Python 中 pep 规范不建议使用 lambda,一般和 map reduce filter sorted 等函数一起用
    raiz
        83
    raiz   56 天前
    Kotlin 的 lambda 是目前见过的最舒服的哈哈
    xfriday
        84
    xfriday   56 天前
    就是匿名函数,别当是什么高级货
    bluehr
        85
    bluehr   56 天前
    推荐《 Java8 实战》,看这本书看了就会了
    xgfan
        86
    xgfan   56 天前
    回楼主:这玩意儿多用,就会上瘾了。

    ------
    回楼上某些人:
    都快 2020 年了,CRUD 项目还不用 lambda,那可真够水的。
    至于自己是不是在做 CRUD 项目,心中有数就行。
    FrankHB
        87
    FrankHB   56 天前   ♥ 3
    看来又是个 ALGOL-like 语言学残的……补习一下历史罢。
    世界上本来就没什么正经的函数(function) ,先是在 1930 年代 A.Church 提出 λ 演算里用于替换绑定变量为其它表达式的 λ 抽象以及把 λ 抽象绑定到一个名称作为变量的用法,后是 1950 年代 J.McCarthy 明确用这样的方法,来实现的一般意义上的所谓的函数。这样,λ 抽象实质上就是所谓的匿名函数(anonymous) 。(在原始的 λ 演算中,这些匿名函数都是所谓的纯函数(pure function) ,之后有另外的扩展,但这个意义上正经地搞是在 1970 年代以后的事。)
    之后(从 1950 年代末开始),一坨不上道的 ALGOL-like 语言把函数弱化成过程(procedure) 乃至子例程(subroutine) 偷换概念,让函数总是总是具有所谓的函数名,先接触这类语言入门的用户就被念歪经的设计整残了;如 Java 之流的更叒鸡的语言把过程继续阉割,去掉了所谓的自由函数(free function) ,叠床架屋依附于所谓的对象(原本对象就跟类的实例无关,考虑到 Java 照抄某些语言的历史,这里是牵强附会)之上,搞出什么方法(method) ,数典忘祖;于是用这样的语言入门的用户更加不会正常的思维方式了。现在一坨语言重新引入 lambda 表达式来表达 λ 抽象,说到底不过是矫治习惯不正常的理解困难的设计的症状,要求端正视听罢了——只不过很遗憾,因为兼容和历史包袱,已有的半残的“函数”或者更残废的“方法”的语法还是被保留,以至于理解起来更容易迷糊和浪费时间。
    (至于在子例程以外的函数的其它实现,如 coroutine 和 continuation 也是很早的支线,比 Java 资格老大概 30 年,这里按下不表,等 Java 之流的语言先赶上再说。)

    当然,不够正经的、歧义满天飞的所谓函数数学早已有之,历史上翻来覆去倒腾了几百年也没个谱,后来才发现严格意义上可以是一回事(例如,以所谓可计算函数(computable function) 作为模型): https://en.wikipedia.org/wiki/History_of_the_function_concept
    和这样的模型比较接近的是一般大学高等数学会教你的基于 Cartesian product 模型化的映射(map) 。数学中更常见的所谓的“函数”和泛函(functional) 都是其缩水版,要求值域是实数,这在日常应用中往往是多余的限制;高中用的“函数”的 Dirchlet 定义,更是连定义域都锁死了,也不讲上域(codomain) ;除了数理逻辑讨论的一些概念,对语法和语义的分割也聊胜于无。所以对理解关心如何用代码的描述和解决计算问题的角度来说,用这些不够严格的传统数学概念,大多讲了白讲。
    现代编程语言常规支持表达的某一类偏可计算函数(partial computable function),除了不可解度(不超越图灵完备)以外,比映射能实现的计算作用(computational effect) 更强,例如允许副作用(side effect) ,也不要求是全函数(totality) 保证确定性终止。(倒是某些 FP 语言会别有用心地妄想把其中某几个特性干掉给阉回去。) Java 之流虽然叒鸡,但是比起来还算是比较正经的了。
    exoticknight
        88
    exoticknight   55 天前
    不就是匿名函数?为什么纠结……
    QdouHuiQwaiLai
        89
    QdouHuiQwaiLai   54 天前
    在 python 里面就是只能写一行的匿名函数吧 不用也没关系
    yinft
        90
    yinft   54 天前
    题主是不是没写过 js,写一段时间 js,再回头 java 用 lambda,你就会发现很顺手了
    thinkmore
        91
    thinkmore   53 天前
    @wuwudeqi 看看这篇文章,我觉得写得还可以 https://juejin.im/post/5d536870e51d4561c6784066

    建议先从简单的写起,先用来改造你的 for 循环,然后再一步一步试探
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   831 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 32ms · UTC 18:59 · PVG 02:59 · LAX 10:59 · JFK 13:59
    ♥ Do have faith in what you're doing.