Java中Lambda表达式的正确使用姿势

        Java8中的最大变化就是引入了Lambda表达式,现在都2090年了,还不会用Lambda表达式的同学们可以关注哀家写的文章,让我们一起感受Lambda带来的便利。

        不是在具体应用场景下写的代码都是耍流氓,所以首先我们建立一个简单的场景。在2090年的我们几乎天天都在刷抖音或拍短视频,抖音中每个账号都是一个用户,我们创建一个User类代表用户,每个用户下可以发布很多短视频作品,我们创建一个Product类代表作品,显而易见,User和Product是一对多的关系,具体代码如下:

/**
 * 抖音用户
 */
@Data
@AllArgsConstructor
public class User {
    //用户名
    private String username;
    //作品
    private List<Product> products;
}


/**
 * 用户作品
 */
@Data
@AllArgsConstructor
public class Product {
    //作品名称
    private String name;
    //作品时长
    private Integer length;
}

        例如现在有两个抖音用户,分别为张同学和小鬼,他们都有自己的作品,现在我们用分别初始化一下User和Product,造一些数据,代码如下:

        User zhangtongxue = new User("张同学", Arrays.asList(
                new Product("农村生活1", 60),
                new Product("农村生活2",30),
                new Product("农村生活3",20),
                new Product("农村生活4",63),
                new Product("农村生活5",80)
        ));

        User xiaogui = new User("小鬼", Arrays.asList(
                new Product("撩妹1", 70),
                new Product("撩妹2",35),
                new Product("撩妹3",23)
        ));

        List<User> users = Arrays.asList(zhangtongxue, xiaogui);

        此时得到的一个用户的集合users,那我们如何筛选出users中的作品时长大于60的作品名称呢?不难想到,用两个for循环就搞定了,如下:

    public static Set<String> findProductNames(List<User> users) {
        Set<String> productNames = new HashSet<>();
        for (User user : users) {
            for (Product product : user.getProducts()) {
                if (product.getLength() > 60) {
                    String name = product.getName();
                    productNames.add(name);
                }
            }
        }
        return productNames;
    }

        上面的代码很传统,索然无味,如果使用lambda是不是很酸呢,下面我们使用Stream的方式对上面的代码进行重构,首先使用forEach替换掉for循环。

    public static Set<String> findProductNames(List<User> users) {
        Set<String> productNames = new HashSet<>();
        users.stream()
                .forEach(user -> {
                    user.getProducts().stream()
                            .forEach(product -> {
                                if (product.getLength() > 60) {
                                    String name = product.getName();
                                    productNames.add(name);
                                }
                            });
                });
        return productNames;
    }

        上面代码中虽然使用了流,但是并没有发挥它的作用,事实上还不如两个for循环的代码好呢!因此,是时候引入更符合流风格的代码了,如下:

    public static Set<String> findProductNames(List<User> users) {
        Set<String> productNames = new HashSet<>();
        users.stream()
                .forEach(user -> {
                    user.getProducts().stream()
                            .filter(product -> product.getLength() > 60)
                            .map(product -> product.getName())
                            .forEach(name -> productNames.add(name));
                });
        return productNames;
    }

        现在使用了更符合流风格的代码替换了内层forEach循环,但代码看起来还是非常的繁琐,各种流嵌套起来非常的糟糕。理想的操作莫过于找到一种方法,将用户转化成一个作品的Stream,因为用户是多个,采用flatMap操作,可以把多个Stream合并成一个Stream,代码如下:

    public static Set<String> findProductNames(List<User> users) {
        Set<String> productNames = new HashSet<>();
        users.stream()
                .flatMap(user -> user.getProducts().stream())
                .filter(product -> product.getLength() > 60)
                .map(product -> product.getName())
                .forEach(productName -> productNames.add(productName));
        return productNames;
    }

        这时候代码就比较干净了,也符合了lambda流式操作风格,但是还存在一点问题,就是上述代码仍需手动创建一个Set集合,然后把结果add到集合中。我们希望看到的是整个计算任务是由一连串的Stream操作完成,也就是链式风格的代码要统一,因此我们想到了收集器,即Collectors,下面我们再次修改代码如下:

    public static Set<String> findProductNames(List<User> users) {
        return users.stream()
                .flatMap(user -> user.getProducts().stream())
                .filter(product -> product.getLength() > 60)
                .map(product -> product.getName())
                .collect(Collectors.toSet());
    }

        此时我们最终漂亮的代码已经完成,一步一步的完善,慢慢体会Lambda的强大!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值