首页 > 编程语言 >Java函数式编程(2):流式计算

Java函数式编程(2):流式计算

时间:2022-11-07 06:55:06浏览次数:36  
标签:getAge Java 编程 流式 Employee new Type public

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

 

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());

 

 


 

 

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

 

标签:getAge,Java,编程,流式,Employee,new,Type,public
From: https://www.cnblogs.com/xiangwang1111/p/16864384.html

相关文章

  • java创建文件对象相关构造器和方法
     1、什么是文件?文件是我们保存数据的地方。2、文件流文件在程序中是以流的形式来操作的。流:数据在数据源(文件)和程序(内存)之间经历的路径输入流:数据从数据源(文件)......
  • Java 日志框架学习笔记
    日志概念1.日志文件日志文件是用于记录系统操作事件的文件集合1.1调试日志1.2系统日志系统日志是记录系统中硬件、软件和系统问题的信息,同时还可以监视系统中发生......
  • java多线程生产者消费者线程并发协作测试心得
    图11-17生产者消费者示意图产品classChicken{intid;publicChicken(intid){this.id=id;}}缓冲区(装产品)classContainer{//定......
  • JYY 第十一课 系统编程与基础设施
       ......
  • 3184-2020-Java-国赛-4-2
    这个题有点意思,是解一个二元一次方程,手算很简单,但是怎么用算法来解还真没想过,一下子好像也没什么思路importjava.util.*;importjava.io.*;classMain{publics......
  • java8将日期格式yyyyMM转换为LocalDate
    LocalDate:parseyyyy-MM当我们希望将一个yyyyMM格式的日期转换为LocalDate的时候,不出意外会报错java.time.format.DateTimeParseException因为LocalDate是需要指定到具......
  • Java IO流
    1、创建文件对象相关构造器和方法newFile(Stringpathname)//根据路径构建一个File对象newFile(Fileparent,Stringchild)//根据父目录文件+子路径构建newFile(Strin......
  • javaSE基础-异常
    异常(Exception)异常相关概念异常:是在运行时期发生的不正常情况。运行时异常:可以正常编译,只有在代码运行的过程中,由于参数运算的数据导致异常。编译时异常:编译检查时......
  • java--Stream流基础
    Stream流操作方法执行完此方法之后,Stream流依然可以继续执行其他操作Stream流的思想 Stream流的三类方法  获取Stream流    好比创建一条流水线,并把数据放......
  • java 集合
    packagecom.tedu.day1302;importjava.util.ArrayList;importjava.util.Collection;publicclassStudy_Collection{publicstaticvoidmain(String[]args)......