您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~

 

Lambda表达式虽然将接口作为代码块赋值给了变量,但如果仅仅只是Lambda表达式,还无法让Java由量变引起质变。真正让Lambda能够发挥出巨大威力的,就是流式计算。

所谓流式计算,就是让数据像在流水线上一样,从一道工序流转到下一道工序。就像这样:

 

 

 

 

如果把数据处理的方式比作流水线,那么Spark、Storm和Flink就是目前市面上头部的三家工厂。它们有各种各样的数据装配间(也就是各种处理数据的算子),将数据按照所需加工成型。所以,不懂流式计算根本就做不了大数据开发。上面那张图,如果换成流式计算的,就是这样:

 

 

 

Lambda表达式就变成了一个个的数据装配间。

还是以实际的代码例子来说明。假如有这样的代码:

/**
 * 雇员数据
 *
 * @author 湘王
 */
public class Employee {
    public enum Type { MANAGER, SELLER, OFFICER };
    private String name;
    private String genger;
    private Integer age;
    private boolean married;
    private Type type;
    public Employee(final String name, final String genger, final Integer age, final boolean married, final Type type) {
        super();
        this.name = name;
        this.genger = genger;
        this.age = age;
        this.married = married;
        this.type = type;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGenger() {
        return genger;
    }
    public void setGenger(String genger) {
        this.genger = genger;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public boolean isMarried() {
        return married;
    }
    public void setMarried(boolean married) {
        this.married = married;
    }
    public Type getType() {
        return type;
    }
    public void setType(Type type) {
        this.type = type;
    }
    @Override
    public String toString() {
        return this.name + "(" + this.genger + ")-" + this.age;
    }
}

 

 

如果想筛选28岁以下的员工,并按年龄排序,用老办法只能这么做:

List<Employee> employees = Arrays.asList(
        new Employee("张勇", "男", 28, true, Employee.Type.MANAGER),
        new Employee("李强", "男", 22, false, Employee.Type.SELLER),
        new Employee("王武", "男", 32, false, Employee.Type.SELLER),
        new Employee("梅丽", "女", 26, true, Employee.Type.OFFICER),
        new Employee("郑帅", "男", 29, false, Employee.Type.OFFICER),
        new Employee("曾美", "女", 27, true, Employee.Type.SELLER),
        new Employee("郝俊", "男", 22, true, Employee.Type.SELLER),
        new Employee("方圆", "女", 24, false, Employee.Type.SELLER)
);

// 传统筛选数据的方法
// 筛选28岁以下的员工
List<Employee> list1 = new ArrayList<>();
for(Employee employee : employees) {
    if (employee.getAge() < 28) {
        list1.add(employee);
    }
}
// 按年龄排序
list1.sort(new Comparator<Employee>() {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.getAge().compareTo(o2.getAge());
    }
});

 

如果要转换成Lmabda表达式的话,就是这样:

/**
 * 雇员函数式接口
 *
 * @author 湘王
 */
@FunctionalInterface
public interface EmployeeInterface<T> {
    boolean select(T t);
}



public static List<Employee> filter(List<Employee> employees, EmployeeInterface<Employee> ei) {
    List<Employee> list = new ArrayList<>();
    for(Employee employee : employees) {
        if (ei.select(employee)) {
            list.add(employee);
        }
    }
    return list;
}



// 使用Lambda表达式得到28岁以下的员工
List<Employee> list2 = filter(employees, employee -> employee.getAge() < 28);

// 按年龄排序
list2.sort((e1, e2) -> e1.getAge().compareTo(e2.getAge()));

 

 

可以看到,这虽然用了Lambda表达式替代了旧的方法,但可能要写大量的函数式接口,Lambda沦为鸡肋,完全谈不上简便快速,更别说优雅!

所以,这时候如果用流式计算,那简直不要太优雅:

// Lambda表达式 + 流式计算
List<Employee> list3 = employees
                                // 生成「流」
                                .stream()
                                // 过滤
                                .filter(emp -> emp.getAge() < 28)
                                // 排序
                                .sorted((o1, o2) -> o1.getAge().compareTo(o2.getAge()))
                                // 生成新的结果集合
                                .collect(Collectors.toList());

 

 

仅仅几行代码就搞定了,完全没有之前那种「傻大黑粗」的感觉了。

上面的代码,可以用这幅图来还原:

 

 

 

1、先用filter算子(流式计算中的函数,或者方法,在大数据中统称为算子,我也习惯这么称呼)将符合年龄条件的雇员筛选出来;

2、再按照年龄从低到高排序;

3、将排好序的员工列表输出出来。

就是这么简单粗暴!

就像藏宝图一样,只有将Lambda表达式和流式计算这两张碎片拼起来,才是完整的Java函数式编程。

 

所有的流式计算算子可以分为两大类:中间操作和终端操作。

1、中间操作:返回另一个流,如filter、map、flatMap等;

2、终端操作:从流水线中生成结果,如collect、count、reduce、forEach等。

 

现在,咱们已经找到了函数式编程这个宝藏。那么再回到最初的问题:当要实现某宝、某东和某哈哈的员工联谊并解决单身问题时,有更好的办法吗?

当然有,而且只用一行代码就可以搞定:

List<Employee> unMarriedList4 = list.stream().filter(company -> Company.Type.BIG == company.getType()).flatMap(companys -> companys.getEmployees().stream()).filter(Employee::isMarried).sorted(Comparator.comparing(Employee::getAge)).collect(Collectors.toList());

 

 


 

 

感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~

 

原文地址:http://www.cnblogs.com/xiangwang1111/p/16864384.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性