Lambda表达式和流式编程

1.lambda表达式

1.无参无返回值

package com.zhang.lambda;

public interface Demo01 {
    void method();

    /**
     * java8之后接口中支持添加非抽象方法和变量
     * 在JDK 1.8版本之后允许在接口中定义非抽象的静态方法,也可以出现静态常量。比如我们可以把一些通用的,
     * 工具性的东西直接定义在其中
     *
     * @param args
     */
    public static void main(String[] args) {
        Demo01 demo = () -> {
            System.out.println("lambda无参无返回值,一条语句");
        };
        demo.method();

        Demo01 demo1 = () -> System.out.println("lambda无参无返回值,一条语句时{}可省略");

        demo1.method();
        int n = 5;//默认被fianl修饰
        Demo01 demo2 = () -> {
            System.out.println("lambda无参无返回值,多条语句时{}不可省略");
            // n++; //n默认被fianl修饰,不可改变
            System.out.println(n);
        };
        demo2.method();

    }
}

运行结果:
lambda无参无返回值,一条语句
lambda无参无返回值,一条语句时{}可省略
lambda无参无返回值,多条语句时{}不可省略
5

Process finished with exit code 0

注意

  1. lambda表达式的语句体只有一条时,可以省略{},多条时不可省略
  2. lambda表达式只能引用被final修饰的外层局部变量

2.有一个参数无返回值

package com.zhang.lambda;

public interface Demo02 {
    void method(int num);

    public static void main(String[] args) {
        Demo02 demo = (int num) -> {
            System.out.println(num);
        };
        demo.method(200);

        //参数类型可以省略,参数可以随便定义
        Demo02 demo1 = (n) -> {
            System.out.println(n + 100);
        };
        demo1.method(300);

        //一个参数时,()可以省略,一条语句时,可以省略{}
        Demo02 demo2 = n -> System.out.println(n + 100);
        demo2.method(300);

        //多条语句时,不可以省略{}
        int m = 3;
        Demo02 demo3 = n -> {
            System.out.println(n + 100);
            System.out.println(m);
        };
        demo3.method(300);
    }
}

运行结果:
200
400
400
400
3

注意

  1. lambda表达式只有一个参数时,参数类型可以省略,参数名可以是任意名称
  2. lambda表达式只有一个参数时,参数外的()可以省略

3.多个参数无返回值

package com.zhang.lambda;

public interface Demo03 {
    void method(int num, String name);

    public static void main(String[] args) {
        //多个参数时,参数类型可以省略,()不可省略
        Demo03 demo = (n, str) -> {
            System.out.println(n + "===" + str);
            System.out.println("多个参数");
        };
        demo.method(100, "test");
    }
}

运行结果:
100===test
多个参数

注意:

​ lambda表达式有多个参数时,参数外的()不可省略

4.有参数有返回值

package com.zhang.lambda;

public interface Demo04 {
    int method(int num);

    public static void main(String[] args) {
        Demo04 demo = (n) -> {
            return n;
        };
        System.out.println(demo.method(100));
        
        //单行语句可省略{}和return
        Demo04 demo1 = (n) -> n;
        System.out.println(demo1.method(100));
    }
}

运行结果:
100
100

注意:

  1. 有返回值的lambda表达式,如果方法体只有一条语句,可以同时省略{}和return

  2. 虽然lambda表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以用lambda表达式来实现。

    lambda规定接口中只能有一个需要被实现的抽象方法,不是规定接口中只能有一个方法,称为函数式接口

总结:

->左边:

  • 参数类型可以不写
  • 如果只有一个参数,()可以省略

->右边:

  • {}将方法体的具体内容包裹起来
  • 方法体只有一条语句时,{}可以省略不写
  • 方法体只有一条语句,且有返回值时,{}和return可以省略不写

2.函数式接口

  1. 接口类上加@FunctionalInterface注解的是函数式接口

  2. 函数式接口只能有一个抽象方法,其他的可以有default,static,Object里的public方法等

  3. 作用:在java中主要用在lambda表达式上

  4. Comparator,Runnable,Callable都是函数式接口(注意:Comparable并没有被标记为函数式接口)

代码示例:

package com.zhang.func;

@FunctionalInterface
public interface Demo01 {
    //抽象方法
    void method();

    //静态方法
    public static void main(String[] args) {

    }

    //静态方法
    static void method1() {
    }

    //default修饰的方法
    default void method2() {
    }

    //object里面的public方法
    public boolean equals(Object obj);
}

内置函数式接口

  • 使lambda表达式的运用方便
  • 主要有以下四类

1.消费型接口

代码示例1(遍历list):

package com.zhang.func;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

public class FunInterface {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList();
        Collections.addAll(list, 10, 40, 20, 40, 30, 54, 36);
        System.out.println(list);
        //匿名内部类遍历
        Consumer consumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer o) {
                System.out.println(o);//o就是list中的元素
            }
        };
        list.forEach(consumer);

        //lambda表达式遍历
        list.forEach((elem) -> {
            System.out.println(elem);
        });

    }
}

运行结果:
[10, 40, 20, 40, 30, 54, 36]
10
40
20
40
30
54
36
10
40
20
40
30
54
36

Process finished with exit code 0

代码示例2(遍历map):

package com.zhang.func;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

public class FunInterface1 {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("cn", "China");
        map.put("jp", "Japan");
        map.put("us", "the United States");
        map.put("us", "America");
        map.put("uk", "England");
        map.put("en", "England");
        //匿名内部类遍历
        BiConsumer biConsumer = new BiConsumer<String, String>() {
            @Override
            public void accept(String o, String o2) {
                System.out.println(o+"------>"+o2);
            }
        };
        map.forEach(biConsumer);
        //lambda表达式遍历
        map.forEach((o,o2)-> System.out.println(o+"--->"+o2));
    }
}

运行结果:
jp------>Japan
uk------>England
en------>England
cn------>China
us------>America
jp--->Japan
uk--->England
en--->England
cn--->China
us--->America

Process finished with exit code 0

2.断言型接口

代码示例1:

package com.zhang.func;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

/**
 * 删除成绩小于60的
 */
public class FunInterface3 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList();
        Collections.addAll(list, 10, 40, 20, 40, 30, 60, 80, 70);
        //匿名内部类
        Predicate predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer o) {
                if (o < 60) {
                    return true;
                }
                return false;
            }
        };
        list.removeIf(predicate);
        System.out.println(list);

        List<Integer> list2 = new ArrayList();
        Collections.addAll(list2, 10, 40, 20, 40, 30, 60, 80, 70);
        //lambda表达式
        list2.removeIf(elem -> {
            if (elem < 60) return true;
            return false;
        });
        System.out.println(list2);

    }
}

[60, 80, 70]
[60, 80, 70]

Process finished with exit code 0

代码示例2:

package com.zhang.func;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

/**
 * 保留成绩小于60的
 */
public class FunInterface4 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList();
        Collections.addAll(list, 10, 40, 20, 40, 30, 60, 80, 70);
        list = retainIf((elem) -> {
            if (elem < 60) return true;
            return false;
        }, list);
        System.out.println(list);//[10, 40, 20, 40, 30]

    }

    public static List retainIf(Predicate<Integer> predicate, List<Integer> list) {
        List list2 = new ArrayList();
        for (int i = 0; i < list.size(); i++) {
            int elem = list.get(i);
            if (predicate.test(elem)) {
                list2.add(elem);
            }
        }
        return list2;
    }
}

3.方法引用

当lambda表达式的方法体仅仅调用一个已经存在的方法,而不做任何其他的操作,对于这种情况,可以通过一个方法名来引用已经存在的方法,属于简化版的lambda表达式

方法引用的操作符是双冒号::

代码示例1:

package com.zhang.method;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
import org.w3c.dom.ls.LSOutput;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

public class MethDemo01 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList();
        Collections.addAll(list, 10, 40, 20, 40, 30, 54, 36);
        //匿名内部类遍历
        Consumer consumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer o) {
                System.out.println(o);//o就是list中的元素
            }
        };
        list.forEach(consumer);
        //lambda表达式遍历
        list.forEach((elem) -> {
            System.out.println(elem);
        });
        System.out.println("========简化========");
        //简化为方法引用:
        list.forEach(System.out::println);//对象引用::实例方法名

    }
}

代码示例2:

package com.zhang.method;

import java.util.function.Supplier;

public class MethDemo02 {
    public static void main(String[] args) {
        Student student = new Student(1, "zhangsan", 89.0, 23);
        //供给型函数
        //匿名内部类
        Supplier supplier = new Supplier<String>() {
            @Override
            public String get() {
                return student.getName();
            }
        };
        System.out.println(supplier.get());

        //lambda表达式
        Supplier supplier1 = () -> student.getName();
        System.out.println(supplier1.get());

        System.out.println("======简化=====");
        
        Supplier supplier2 = student::getName;//对象引用::实例方法名
        System.out.println(supplier2.get());


    }
}
zhangsan
zhangsan
======简化=====
zhangsan

代码示例3:

package com.zhang.method;

import java.util.Comparator;

public class MethDemo03 {
    public static void main(String[] args) {
        //匿名内部类
        Comparator comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                // return o1 - o2;
                return Integer.compare(o1, o2);
            }
        };
        System.out.println(comparator.compare(10, 20));

        //lambda表达式
        Comparator<Integer> comparator1 = (o1, o2) -> {
            return Integer.compare(o1, o2);
        };
        System.out.println(comparator1.compare(40, 30));

        System.out.println("==============简化============");
        Comparator<Integer> comparator2 = Integer::compare;//类名::静态方法名
        System.out.println(comparator2.compare(40, 30));
    }
}
-1
1
==============简化============
1

4.流式编程

1. 流式编程(Stream)是专门针对集合的一系列操作,与lambda表达式相结合时,极大的精减了代码,提高了编程效率

2.Stream的三个操作步骤:

第一步:创建Stream:从一个数据源,如从集合或数组中获取流

第二步:中间操作:对数据源的数据进行各种中间操作

第三步:终止操作:执行中间操作,并产生结果


代码示例1(中间操作和终止操作):

package com.zhang.stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;

public class StreamDemo01 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList();
        Collections.addAll(list, 10, 40, 20, 40, 30, 60, 98, 87, 74, 98);
        //第一步:创建流
        Stream<Integer> stream = list.stream();
        //第二步:各种中间操作 filter过滤 ;distinct 去重;sorted排序,默认升序,通过实现比较器来降序排列;
        //skip跳过;map 函数式编程 每个-5分
        stream = stream.filter((item) -> {
            if (item > 60) return true;
            return false;
        }).distinct()
                .sorted((x1, x2) -> x2 - x1)
                .skip(1)
            	.map(x -> x - 5);
        //第三步:终止操作
        //stream.forEach(System.out::println);// 82 69
        System.out.println(stream.count());//2
        //System.out.println(stream.max((x1,x2)->{return x1-x2;}));//Optional[82]
    }
}

代码示例2(创建stream):

package com.zhang.stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.UnaryOperator;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamDemo02 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList();
        Collections.addAll(list, 10, 40, 20, 40, 30, 60, 98, 87, 74, 98);

        System.out.println("========创建流,方法一 list.stream()===========");
        Stream<Integer> stream = list.stream();
        stream.forEach(System.out::println);

        System.out.println("========创建流,方法二 list.parallelStream(),并行流,速度快,顺序不确定===========");
        Stream<Integer> stream2 = list.parallelStream();
        stream2.forEach(System.out::println);

        System.out.println("========创建流,方法三 Stream.of() 直接传数值===========");
        Stream<Integer> stream3 = Stream.of(10, 40, 20, 40, 30, 60, 98, 87, 74, 98);
        stream3.forEach(System.out::println);

        System.out.println("========创建流,方法四 Arrays.stream() ====IntStream=======");
        int[] arr = {10, 40, 20, 40, 30, 60, 98, 87, 74, 98};
        IntStream stream4 = Arrays.stream(arr);
        stream4.forEach(System.out::println);

        System.out.println("========创建流,方法五 Stream.generate() 供给型函数=======");
        Stream<Double> stream5 = Stream.generate(() -> Math.random());
        stream5.limit(10).forEach(System.out::println);

        System.out.println("========创建流,方法六 Stream.iterate()=======");
        /*UnaryOperator unaryOperator=new UnaryOperator<Integer>() {
            @Override
            public Integer apply(Integer o) {
                return o+1;
            }
        };
        Stream stream6 = Stream.iterate(10, unaryOperator);*/
        Stream stream6 = Stream.iterate(10, n->n+1);
        stream6.limit(10).forEach(System.out::println);

    }
}

========创建流,方法一 list.stream()===========
10
40
20
40
30
60
98
87
74
98
========创建流,方法二 list.parallelStream(),并行流,速度快,顺序不确定===========
98
60
74
98
87
20
40
10
30
40
========创建流,方法三 Stream.of() 直接传数值===========
10
40
20
40
30
60
98
87
74
98
========创建流,方法四 Arrays.stream() ====IntStream=======
10
40
20
40
30
60
98
87
74
98
========创建流,方法五 Stream.generate() 供给型函数=======
0.7431622730319491
0.43443161309550227
0.8645667709688453
0.6877686922162565
0.6140667710241576
0.6693309354076292
0.31653464589793023
0.05020886948639036
0.9681932539200534
0.5413376067167883
========创建流,方法六 Stream.iterate()=======
10
11
12
13
14
15
16
17
18
19

Process finished with exit code 0

posted @ 2021-08-19 10:40  wlbsm  阅读(138)  评论(0编辑  收藏  举报