java中Lambda+流式编程讲解(心得片)

x33g5p2x  于2021-12-03 转载在 Java  
字(8.4k)|赞(0)|评价(0)|浏览(352)

首先举一个例子来说明,我们要在一群人里面刷选一些,首先自己写一个Person类:

package 任务十三__流式计算.公司;

import java.util.Objects;

/** * @author ${范涛之} * @Description * @create 2021-12-01 22:19 */
public class Person {
    private String name;
    private Integer age;
    private double size;
    private double salary;
    public Person(){}
    public Person(Integer age){
        this.age = age;
    }

    public Person(String name, Integer age, double size, double salary) {
        this.name = name;
        this.age = age;
        this.size = size;
        this.salary = salary;
    }

    @Override
    public  boolean equals(Object o){
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return  false;
        Person student = (Person) o;
        return Double.compare(student.size,size) == 0 &&
                Double.compare(student.salary,salary) == 0 &&
                Objects.equals(name,student.name) &&
                Objects.equals(age,student.age);

    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Person{");
        sb.append("name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append(", size=").append(size);
        sb.append(", salary=").append(salary);
        sb.append('}');
        return sb.toString();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public double getSize() {
        return size;
    }

    public void setSize(double size) {
        this.size = size;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

然后我们开始写主方法:首先在主方法中添加成员:

List<Person> studentList = Arrays.asList(
            new Person("无极",18,188,35000),
            new Person("范涛之",30,188,45000),
            new Person("张荣卡",29,188,35000),
            new Person("秦舒下",24,188,45000),
            new Person("妹妹",32,188,43000)
    );

然后我们开始根据需求提取数据,先用曾经·1我们使用的简单的if语句:

/** * 需求一:工资超过25000 * @param list * @return */
    public List<Person> fillterSudent1(List<Person> list){
        List<Person> result = new ArrayList<>();
        for (Person student :list){
            if (student.getSalary() >25000){
                result.add(student);
            }
        }
        return result;
    }
/** * 需求二:身高超过一米七 */
    public List<Person> fillterSudent2(List<Person> list){
        List<Person> result = new ArrayList<>();
        for (Person student :list){
            if (student.getSize()>170){
                result.add(student);
            }
        }
        return result;
    }

我们通过这两个需求可以发现其实原始方法中只有一行核心代码是不一样的:

所以我们便有了优化方案那就是使用:策略模式:对算法的包装

我们新建一个接口:MyPredicate

然后再主方法中声明:我们将上面一样的核心代码部分改为:myPredicate.test(student)

/** * 优化方案1:策略模式+匿名内部类 */
    public List<Person> fillterSudent3(List<Person> list,MyPredicate<Person> myPredicate){
        List<Person> result = new ArrayList<>();
        for (Person student :list){
            if (myPredicate.test(student)){
                result.add(student);
            }
        }
        return result;
    }

然后写筛选的方法继承接口:

public void test3(){
        List<Person> list = fillterSudent3(studentList, new MyPredicate<Person>() {
            @Override
            public boolean test(Person o) {
                return o.getSalary()>25000;
            }
        });
        for (Person student:list){
            System.out.println(student);
        }
    }

继续优化:用lambda替换匿名内部类

/** * 继续优化 */
    public void test4(){
       List<Person> list = fillterSudent3(studentList,(x)->x.getSalary()>25000);
        for (Person student:list){
            System.out.println(student);
        }
    }

使用流式编程优化:

/** * 优化方案3:stream api */
    @Test
    public void test5() {
        studentList.stream()
                .filter((x) -> x.getSalary() > 25000)
                .filter((x) -> x.getAge() > 25)
                .limit(2)
                .forEach(System.out::println);
        System.out.println("------------------------");

测试:

分割线------------------------------------------------------

基础语法学习:

Java8中引入了一个新的操作符"->”该操作符称为箭头操作符或Lambda操作符
箭头操作符将Lambda衣达式拆分成两部分:
左侧: L ambda衣达式的参数列表
右侧: Lambda表达式中所需执行的功能,即Lambda体
依赖于函数式接口,Lambda衣达式即对接口的实现

1:第一个是无参无返回值:

原本写法:

public  void test1(){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("1");
            }
        };
    }

使用Lambda优化:

public void test1(){
        Runnable runnable = () -> {
            System.out.println("1");
        };
    }

2:有一个参数,无返回值使用线程Consumer

public void test2(){
        Consumer<String> com = (x) -> {
            System.out.println(x);
        };
        com.accept("办公室乱死了烦!!");
    }

2.1:有一个参数,无返回值使用线程Consumer,省略括号

@Test
    public void test3(){
        Consumer<String> com = x-> {
            System.out.println(x);
        };
        com.accept("真的烦死了能不能声音小点!!!");
    }

3:语法四:两个参数以上,有返回值,并且lambda中有多条语句

/** * 语法四:两个参数以上,有返回值,并且lambda中有多条语句 */
    public void test4(){
        Comparator<Integer> com =(x,y) ->{
            System.out.println("111");
            return Integer.compare(x,y);
        };
    }

3.1:lambda体中只有一条语句,return 和大括号都可以省略不写

/** * 语法五:lambda体中只有一条语句,return 和大括号都可以省略不写 */
    public void test5(){
        Comparator<Integer> com =(x,y) -> Integer.compare(x,y);
    }

这里稍微哦总结一下这四个接口,其中一个是我们上面用到的Consumer接口,为什么他们要叫做消费性接口呢?简单说明一下就是:所谓消费性也就是花费了,没了,就比如你去花钱买了一小时的按摩,一小时过后你出来会发现你并没有多了什么东西只是舒服了,这就是消费,我们从后面的抽象方法也可也看出来:void accept(T t)很明显,有参数却没有返回值,这就是消费型!

供给型也就是所谓的“无私奉献”,没有参数却可以有返回值!

函数型就是既有参数也有返回值

断言型接口:所谓断言就是判断对或错嘛,所以就是布尔型!

插入点:--------------------------------------------------------------------

然后我这里说一下关于上面的myPredicate.test(student)这个东西,我们自己新建了一个接口用来接受一系列筛选条件,我这里再说明一个java自带的为了方面这么做的方法:Predicate

---------------------------------------------------------------------------------

消费性: Consumer

/** * 消费型Consumer 需求:传入一个参数做业务处理,不需要返回值 */
    public void  happy(double money, Consumer<Double> con){
        con.accept(money);
    }
    @Test
    public void test1(){
        happy(1000,(m)-> System.out.println("范涛之去洗脚花费了"+m+"元"));
    }

供给型:Supplier

/** * 供给型接口:Supplier 需求:产生指定数量的整数,放到集合中,返回集合 */
    public List<Integer> getNumList(int num, Supplier<Integer> sp){
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i <num; i++) {
            result.add(sp.get());
        }
        return  result;
    }
    @Test
    public  void test2(){
        List<Integer> NumList = getNumList(5,()->(int)(Math.random() * 100));
        System.out.println(NumList);
    }

函数型:

/** * 函数型 传入一个字符串,返回一个新的字符串 */
    public String strHander(String str , Function<String ,String> fun){
        return fun.apply(str);
    }
    public void test3(){
        String result = strHander("武林盟主:",(x)->x+"范涛之");
        System.out.println(result);
    }

断言型:

/** * 断言型 */

    public  List<Person> filterStudent3(List<Person> list, Predicate<Person> myPredicate){
        List<Person> result = new ArrayList<>();
        for (Person student :list){
            if (myPredicate.test(student)){
                result.add(student);
            }
        }
        return  result;
    }

分割线·························································································

流的讲解:stream

创建流:四种方法,主要前两种:

流的终止操作:一种是foreach,要是没有终止操作就不会产生新的流 :

一次性请求全部内容:惰性求值

并行流和串行流:

这里设计一下什么是Forkjoin

假设你要计算从1加到一亿,我们的forkjoin思想就是分成两个线程,一个计算1-五千万第二个计算五千万零1到一亿!

最后讲一下自己对于流式编程的总结理解:其实流式编程整体上就是将你要操作的东西先转换为一种流然后经过一系列的处理比如扁平化啦,比如过滤比如排序等等等等,然后在这中间的步骤根据不同的需求去选择对应的四种类型的流然后去操作,最终输出这个新的流,可以说是用会了就很爽了!

自己也是重新返回去看了自己昨天的代码:

List<Employee> result = list.stream()
                .flatMap(company->company.getEmployees().stream())
// .filter(employee -> employee.getType().equals("OFFICER"))
                .filter(employee -> employee.getAge()>20)
                .filter(employee -> employee.isMarried())
                .filter(employee -> employee.getType()== Employee.Type.MANAGER)
                .sorted(Comparator.comparing(Employee::getAge))
                .collect(Collectors.toList());

        for (Employee employee:result){
            System.out.println(employee);
        }

在任务的基础上通过自己的不同命令的调试和理解去增加自己对于流式编程的熟悉与使用!

最后说一下自己晕了的地方:也就是在上次的习题中:最后的地方,自己没有搞清楚返回值是什么,创建流操作的地方是什么,下面附上自己尝试过的代码:

/** * 公司流 */
// List<Employee> result = list.stream()
// .flatMap(company -> company.getEmployees().stream())
// .filter(employee -> !employee.isMarried())
// .sorted(Comparator.comparing(Employee::getAge))
// .collect(Collectors.toList());
//
// for (Employee emp :result){
// System.out.println(emp.toString());
// }

// List<Employee> result = list.stream()
// .filter(company -> company.getType()==(Company.Type.SMALL))
// .flatMap(company ->company.getEmployees().stream())
// .filter(employee -> employee.getAge()>20)
// .filter(employee -> employee.isMarried())
// .filter(employee -> employee.getType()== Employee.Type.MANAGER)
// .sorted(Comparator.comparing(Employee::getAge))
// .collect(Collectors.toList());
// for (Employee employee:result){
// System.out.println(employee);
// }

// List<Company<Employee>> result = list.stream()
// .filter(company -> company.getType()== Company.Type.BIG)
// .collect(Collectors.toList());
//
// for (Company company:result){
// System.out.println(result);
// }

        /** * 创建公司流 然后为了去获取公司 */
        List<Company<Employee>>  result1 = list.stream()
                .filter(company ->  company.getType()== Company.Type.BIG)
                .collect(Collectors.toList());
        for (Company company:result1){
            System.out.println(result1);
        }

        /** * 创建公司流 然后为了去获取员工 */
        List<Employee>  result2 = list.stream()
                .flatMap(company -> company.getEmployees().stream())
                .filter(employee -> employee.isMarried())
                .collect(Collectors.toList());

        /** * 创建员工流 然后为了去获取员工 */
        List<Employee> result3 = employees.stream()
                .filter(employee -> employee.isMarried())
                .collect(Collectors.toList());
        for (Employee employee:result3){
            System.out.println(result3);
        }

自己的理解:

未来的自己再次返回来看自己的文章一定会很有感触吧!!

相关文章

最新文章

更多

目录