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

小白请教一下 JDK8 Lambda 表达式问题

  •  1
     
  •   SuperHzw · 2019-02-11 15:11:31 +08:00 · 4137 次点击
    这是一个创建于 2103 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在项目升级用 jdk8,使用的时候遇到了一个问题,请教一下大家

    实体类:
    Family{
    	private List<Person> person;
        ...
    }
    Person{
        private String age;
        ...
    }
    

    现在我要输出每个家庭中的每个人的年龄 jdk8 之前的写法:

    if(!familyList.isEmpty()){
    	for(Family f : familyList){
        	    if(!f.getPerson.isEmpty()){
            	for(Person p : f.getPerson){
                	    system.out.println(p.getAge());
                }
            }
        }
    }
    

    感觉很繁琐,可以用 Lambda 表达式来简化代码吗?

    28 条回复    2019-02-13 09:10:25 +08:00
    lqw3030
        1
    lqw3030  
       2019-02-11 15:41:31 +08:00 via iPhone
    .forEach(()->{})套两层
    arrow8899
        2
    arrow8899  
       2019-02-11 15:44:55 +08:00
    familyList.forEach(fml -> fml.getPerson().forEach(person -> System.out.println(person.getAge())));
    no1xsyzy
        3
    no1xsyzy  
       2019-02-11 15:50:44 +08:00
    flatMap
    reeco
        4
    reeco  
       2019-02-11 16:01:54 +08:00   ❤️ 4
    familyList.stream().map(Family::getPerson).flatMap(List::stream).map(Person::getAge).forEach(System.out::println);
    thetydead
        5
    thetydead  
       2019-02-11 16:02:19 +08:00
    familyList.forEach(f -> f.getPerson().forEach(System.out::println));
    xhinliang
        6
    xhinliang  
       2019-02-11 16:02:26 +08:00
    flatMap 正解
    zts1993
        7
    zts1993  
       2019-02-11 16:15:35 +08:00
    我觉得用 forEach 都不好意思说自己用的是 Lambda,这和 forr 有啥区别嘛 : )
    LastingTime
        8
    LastingTime  
       2019-02-11 16:49:18 +08:00
    过分追求 Lambda 去简化本不需要简化的代码, 不见得有什么好处.
    另外你这几层都得判空, 更没必要了..
    DsuineGP
        9
    DsuineGP  
       2019-02-11 17:25:57 +08:00
    flightInfos.stream().map(Family::getPerson).flatMap(Collection::stream).map(Person::getAge).forEach(System.out::println);
    qiyuey
        10
    qiyuey  
       2019-02-11 19:00:19 +08:00
    楼上很多使用了 stream,但是 stream 比较消耗性能,单纯的 forEach 没必要使用 stream。
    SuperHzw
        11
    SuperHzw  
    OP
       2019-02-12 00:14:49 +08:00 via iPhone
    @DsuineGP 之前研究了一下就是用你这样子的形式,但是这样子判断为空就没了,想加入 optional,但是这样就不知道要怎么写了😂
    SuperHzw
        12
    SuperHzw  
    OP
       2019-02-12 00:15:56 +08:00 via iPhone
    @qiyuey 看书上的介绍 好像用 stream 是比较节省成本的?
    SuperHzw
        13
    SuperHzw  
    OP
       2019-02-12 00:19:08 +08:00 via iPhone
    @xhinliang @reeco @no1xsyzy @arrow8899
    有使用 flatMap,但是还有两个非空判断,想加入 optionnal 解决,就不知道怎么写了,网上找了一下也没有结论
    wxkvEX
        14
    wxkvEX  
       2019-02-12 00:56:07 +08:00 via iPhone
    @SuperHzw 为啥要 optional,非空判断可以加 family 的流里,用 filter 就可以
    nl101531
        15
    nl101531  
       2019-02-12 08:07:56 +08:00
    @SuperHzw 你这里只是 isEmpty 判断,实际上集合中没有元素 Stream 这个链路只会构造起来,但是不会执行的,不用考虑。如果是 NPE 判断可以按照下面方式。

    Optional.ofNullable(familyList)
    .orElse(Collections.emptyList())
    .stream()
    .filter(x -> !CollectionUtils.isEmpty(x.person))
    .flatMap(x -> x.person.stream())
    .forEach(x -> System.out.println(x.age));
    SuperHzw
        16
    SuperHzw  
    OP
       2019-02-12 10:17:30 +08:00
    @wxkvEX 是的,用 filter 也可以,只是自己好奇在此背景下如何用 stream 和 optional 结合的方式写
    daemonk
        17
    daemonk  
       2019-02-12 10:20:11 +08:00
    isEmpty() 还是有可能 NPE 啊
    SuperHzw
        18
    SuperHzw  
    OP
       2019-02-12 10:24:11 +08:00
    @nl101531 感谢您的解答,厉害!
    jorneyr
        19
    jorneyr  
       2019-02-12 10:34:21 +08:00
    2 个 for 循环比啥都简洁的代码,强用其他写法后代码的可读性降低了很多。
    qiyuey
        20
    qiyuey  
       2019-02-12 10:54:33 +08:00
    @SuperHzw 那是指 stream 长链操作的 lazy 特性,对于单纯的 forEach 只会增加开销。
    no1xsyzy
        21
    no1xsyzy  
       2019-02-12 11:49:35 +08:00
    @qiyuey 真 · 只是为了好看
    流处理理解起来大多数更方便一点所以会觉得好看
    SuperHzw
        22
    SuperHzw  
    OP
       2019-02-12 11:59:27 +08:00 via iPhone
    @qiyuey @no1xsyzy 不只是好看 刚刚写了个测试类试一下 单单两个循环 用 flatmap 速度是比较快的
    qiyuey
        23
    qiyuey  
       2019-02-12 13:26:09 +08:00
    @SuperHzw 你可以多测试几次,另外建议将 print 操作替换为空的方法调用,因为 print 带来的误差还是比较大的。其实这个问题很简单,你可以看一下 stream 的源码,就会发现,无论如何 stream 的性能不可能超过单纯的循环。
    dengtongcai
        24
    dengtongcai  
       2019-02-12 14:03:50 +08:00
    写嵌套,然后 alt+enter 让 idea 帮你改成 lambda
    cyspy
        25
    cyspy  
       2019-02-12 16:07:14 +08:00
    这两次判空完全是不需要的
    SuperHzw
        26
    SuperHzw  
    OP
       2019-02-12 23:46:10 +08:00 via iPhone
    @cyspy 那应该如何处理呢?
    SuperHzw
        27
    SuperHzw  
    OP
       2019-02-12 23:46:36 +08:00 via iPhone
    @qiyuey 好的 明天我会尝试一下
    cyspy
        28
    cyspy  
       2019-02-13 09:10:25 +08:00
    @SuperHzw 无论是 for (:)还是 flatmap 都会自动忽略掉空集合
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5453 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 01:24 · PVG 09:24 · LAX 17:24 · JFK 20:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.