Lambda表达式及Stream API

是Lambda表达式符号,其中左侧为接口方法里的参数,右侧为接口实现类的具体方法,即左侧参数是否符合某种断定条件。

代码示例图

Lambda 表达式_Image_1
在这里插入图片描述
Lambda 表达式_Image_3
Lambda 表达式_Image_4

Lambda表达式的基础语法

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.junit.Test;

/*
* 1、Lambda 表达式的基础语法:Java8中引入了一个新的操做符 "->" 该操做符称为箭头操做符或 Lambda 操做符
 *                             箭头操做符将 Lambda 表达式拆分红两部分:
*
* 左侧:Lambda 表达式的参数列表
* 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
*
* 语法格式一:无参数,无返回值
 *         () -> System.out.println("Hello Lambda!");
*
* 语法格式二:有一个参数,而且无返回值
 *         (x) -> System.out.println(x)
*
* 语法格式三:若只有一个参数,小括号能够省略不写
 *         x -> System.out.println(x)
*
* 语法格式四:有两个以上的参数,有返回值,而且 Lambda 体中有多条语句
 *        Comparator<Integer> com = (x, y) -> {
 *            System.out.println("函数式接口");
 *            return Integer.compare(x, y);
 *        };
*
* 语法格式五:若 Lambda 体中只有一条语句, return 和 大括号均可以省略不写
 *         Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
*
* 语法格式六:Lambda 表达式的参数列表的数据类型能够省略不写,由于JVM编译器经过上下文推断出,数据类型,即“类型推断”
 *         (Integer x, Integer y) -> Integer.compare(x, y);
*
* 上联:左右遇一括号省
* 下联:左侧推断类型省
* 横批:能省则省
*
* 2、Lambda 表达式须要“函数式接口”的支持
* 函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。 可使用注解 @FunctionalInterface 修饰
 *              能够检查是不是函数式接口
*/
public class TestLambda2 {

    @Test
    public void test1(){
        int num = 0;//jdk 1.7 前,必须是 final

        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello World!" + num);
            }
        };
        r.run();
        System.out.println("-------------------------------");
        Runnable r1 = () -> System.out.println("Hello Lambda!");
        r1.run();
    }
    @Test
    public void test2(){
        Consumer<String> con = x -> System.out.println(x);
        con.accept("Lambda Stream API!");
    }
    @Test
    public void test3(){
        Comparator<Integer> com = (x, y) -> {
            System.out.println("函数式接口");
            return Integer.compare(x, y);
        };
    }
    @Test
    public void test4(){
        Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
    }
    @Test
    public void test5(){
//        String[] strs;
//        strs = {"aaa", "bbb", "ccc"};
        List<String> list = new ArrayList<>();
        show(new HashMap<>());
    }
    public void show(Map<String, Integer> map){
    }
    //需求:对一个数进行运算
    @Test
    public void test6(){
        Integer num = operation(100, (x) -> x * x);
        System.out.println(num);
        System.out.println(operation(200, (y) -> y + 200));
    }
    public Integer operation(Integer num, MyFun mf){
        return mf.getValue(num);
    }
}

Lambda四大内置函数式接口

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.junit.Test;

/*
* Java8 内置的四大核心函数式接口
*
* Consumer<T> : 消费型接口
 *         void accept(T t);
*
* Supplier<T> : 供给型接口
 *         T get();
*
* Function<T, R> : 函数型接口
 *         R apply(T t);
*
* Predicate<T> : 断言型接口
 *         boolean test(T t);
*
*/
public class TestLambda3 {
    //Predicate<T> 断言型接口:
    @Test
    public void test4(){
        List<String> list = Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok");
        List<String> strList = filterStr(list, (s) -> s.length() > 3);
        for (String str : strList) {
            System.out.println(str);
        }
    }
    //需求:将知足条件的字符串,放入集合中
    public List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> strList = new ArrayList<>();
        for (String str : list) {
            if(pre.test(str)){
                strList.add(str);
            }
        }
        return strList;
    }
    //Function<T, R> 函数型接口:
    @Test
    public void test3(){
        String newStr = strHandler("\t\t\t Lambda Stream API   ", (str) -> str.trim());
        System.out.println(newStr);

        String subStr = strHandler("Lambda Stream API", (str) -> str.substring(2, 5));
        System.out.println(subStr);
    }
    //需求:用于处理字符串
    public String strHandler(String str, Function<String, String> fun){
        return fun.apply(str);
    }
    //Supplier<T> 供给型接口 :
    @Test
    public void test2(){
        List<Integer> numList = getNumList(10, () -> (int)(Math.random() * 100));
        for (Integer num : numList) {
            System.out.println(num);
        }
    }
    //需求:产生指定个数的整数,并放入集合中
    public List<Integer> getNumList(int num, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Integer n = sup.get();
            list.add(n);
        }
        return list;
    }
    //Consumer<T> 消费型接口 :
    @Test
    public void test1(){
        happy(10000, (m) -> System.out.println("你喜欢吃烧烤,每次消费:" + m + "元"));
    }
    public void happy(double money, Consumer<Double> con){
        con.accept(money);
    }
}

Lambda方法引用与构造器引用

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.junit.Test;

/*
* 1、方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可使用方法引用
 *               (能够将方法引用理解为 Lambda 表达式的另一种表现形式)
*
* 1. 对象的引用 :: 实例方法名
*
* 2. 类名 :: 静态方法名
*
* 3. 类名 :: 实例方法名
*
* 注意:
 *      ①方法引用所引用的方法的参数列表与返回值类型,须要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
 *      ②若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
*
* 2、构造器引用 :构造器的参数列表,须要与函数式接口中参数列表保持一致!
*
* 1. 类名 :: new
*
* 3、数组引用
*
 *     类型[] :: new;
*
*/
public class TestMethodRef {
    //数组引用
    @Test
    public void test8(){
        Function<Integer, String[]> fun = (args) -> new String[args];
        String[] strs = fun.apply(10);
        System.out.println(strs.length);

        System.out.println("--------------------------");

        Function<Integer, Employee[]> fun2 = Employee[] :: new;
        Employee[] emps = fun2.apply(20);
        System.out.println(emps.length);
    }
    //构造器引用
    @Test
    public void test7(){
        Function<String, Employee> fun = Employee::new;
        BiFunction<String, Integer, Employee> fun2 = Employee::new;
    }
    @Test
    public void test6(){
        Supplier<Employee> sup = () -> new Employee();
        System.out.println(sup.get());
        
        System.out.println("------------------------------------");
        
        Supplier<Employee> sup2 = Employee::new;
        System.out.println(sup2.get());
    }
    //类名 :: 实例方法名
    @Test
    public void test5(){
        BiPredicate<String, String> bp = (x, y) -> x.equals(y);
        System.out.println(bp.test("abcde", "abcde"));
        
        System.out.println("-----------------------------------------");
        
        BiPredicate<String, String> bp2 = String::equals;
        System.out.println(bp2.test("abc", "abc"));
        
        System.out.println("-----------------------------------------");
        
        Function<Employee, String> fun = (e) -> e.show();
        System.out.println(fun.apply(new Employee()));
        
        System.out.println("-----------------------------------------");
        
        Function<Employee, String> fun2 = Employee::show;
        System.out.println(fun2.apply(new Employee()));
    }
    //类名 :: 静态方法名
    @Test
    public void test4(){
        Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
        
        System.out.println("-------------------------------------");

        Comparator<Integer> com2 = Integer::compare;
    }
    @Test
    public void test3(){
        BiFunction<Double, Double, Double> fun = (x, y) -> Math.max(x, y);
        System.out.println(fun.apply(1.5, 22.2));

        System.out.println("--------------------------------------------------");
        
        BiFunction<Double, Double, Double> fun2 = Math::max;
        System.out.println(fun2.apply(1.2, 1.5));
    }
    //对象的引用 :: 实例方法名
    @Test
    public void test2(){
        Employee emp = new Employee(101, "张三", 18, 9999.99);
        Supplier<String> sup = () -> emp.getName();
        System.out.println(sup.get());
        
        System.out.println("----------------------------------");
        
        Supplier<String> sup2 = emp::getName;
        System.out.println(sup2.get());
    }
    @Test
    public void test1(){
        PrintStream ps = System.out;
        Consumer<String> con = (str) -> ps.println(str);
        con.accept("Hello World!");

        System.out.println("--------------------------------");

        Consumer<String> con2 = ps::println;
        con2.accept("Hello Java8!");

        Consumer<String> con3 = System.out::println;
    }
}

Stream API的操做步骤

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import org.junit.Test;

/*
* 1、Stream API 的操做步骤:
*
* 1. 建立 Stream
*
* 2. 中间操做
*
* 3. 终止操做(终端操做)
*/
public class TestStreamaAPI {

    //1. 建立 Stream
    @Test
    public void test1(){
        //1. Collection 提供了两个方法  stream() 与 parallelStream()
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream(); //获取一个顺序流
        Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
        //2. 经过 Arrays 中的 stream() 获取一个数组流
        Integer[] nums = new Integer[10];
        Stream<Integer> stream1 = Arrays.stream(nums);
        //3. 经过 Stream 类中静态方法 of()
        Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);
        //4. 建立无限流
        //迭代
        Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);
        stream3.forEach(System.out::println);
        //生成
        Stream<Double> stream4 = Stream.generate(Math::random).limit(2);
        stream4.forEach(System.out::println);
    }
    //2. 中间操做
    List<Employee> emps = Arrays.asList(
            new Employee(102, "李四", 59, 6666.66),
            new Employee(101, "张三", 18, 9999.99),
            new Employee(103, "王五", 28, 3333.33),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(105, "田七", 38, 5555.55)
    );
    /*
      筛选与切片
        filter——接收 Lambda , 从流中排除某些元素。
        limit——截断流,使其元素不超过给定数量。
        skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
        distinct——筛选,经过流所生成元素的 hashCode() 和 equals() 去除重复元素
     */
    //内部迭代:迭代操做 Stream API 内部完成
    @Test
    public void test2(){
        //全部的中间操做不会作任何的处理
        Stream<Employee> stream = emps.stream()
            .filter((e) -> {
                System.out.println("测试中间操做");
                return e.getAge() <= 35;
            });
        //只有当作终止操做时,全部的中间操做会一次性的所有执行,称为“惰性求值”
        stream.forEach(System.out::println);
    }
    //外部迭代
    @Test
    public void test3(){
        Iterator<Employee> it = emps.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
    @Test
    public void test4(){
        emps.stream()
            .filter((e) -> {
                System.out.println("短路!"); // &&  ||
                return e.getSalary() >= 5000;
            }).limit(3)
            .forEach(System.out::println);
    }
    @Test
    public void test5(){
        emps.parallelStream()
            .filter((e) -> e.getSalary() >= 5000)
            .skip(2)
            .forEach(System.out::println);
    }
    @Test
    public void test6(){
        emps.stream()
            .distinct()
            .forEach(System.out::println);
    }
}
相关文章
相关标签/搜索