目录
一、Lambda表达式是什么?什么场景下使用Lambda?
1.Lambda 表达式是什么
2.函数式接口是什么
第二章、怎么用Lambda
1.必须有一个函数式接口
2.省略规则
3.Lambda经常用来和匿名内部类比较
第三章、具体使用举例()
1.案例一,自己写简单Lambda表达式(自定义的函数式接口)
2.案例二,Lambda表达式创建线程(Runnable函数式接口)
3.案例三,Lambda表达式写判断型接口(Predicate函数式接口)
4.案例四,Lambda表达式写比较器(Comparator函数式接口)
5.案例五,Lambda表达式写过滤器(FileFilter函数式接口)
一、Lambda表达式是什么?什么场景下使用Lambda?
 1.Lambda 表达式是什么
 
 1.Lambda 表达式本质上是一个匿名方法,是JAVA8中提供的一种新的特性(一种新的表达方式,以前旧的写法换成新的写法,可以写出更简洁、更灵活的代码)。
我们以前定义一个方法总是想到方法的五要素:
修饰符 返回值类型 方法名(参数列){方法体}2.我要打印一段话,用Lambda翻新成一个匿名方法,语法格式如下:
以前写个方法:
public void prin(){
System.out.println(" 打印这个Lambda啊");
}
现在用Lambda写:
最简单的三要素:
参数列表   操作符箭头   方法体
  ()         ->    {System.out.println(" 打印这个Lambda啊");}
注意:直接把下面这段拿去运行是不行的,忍住先往下看:
() -> { System.out.println(" 打印这个Lambda啊");}在这个基础上我们进行拓展丰富,在参数列表里放一个参数。
注意:这个也不能运行
有一个参数,并且无返回值;
参数列表里放个参数a       操作符箭头        方法体
    (参数a)              ->        System.out.println(a);继续丰富,在参数列表里放两个参数,有返回值。
注意1:前面多了个Comparator com =
注意2:可以复制运行了。因为这段代码前面多了一个Comparator com =,这Comparator是个接口,而且是函数式接口,那么函数式接口是什么。
//有两个以上的参数,有返回值,并且大括号方法体里头多条语句
Comparator com = (a, b) -> {
System.out.println("打印一下");  return Integer.compare(10, 11);
};
2.函数式接口是什么
接口好理解,那什么是函数式接口呢?函数式接口是有且仅有一个抽象方法(不包含object中的方法)的接口。注意:我们只需要关注抽象方法的个数,不用关注其他类型的方法个数。
如图:我们可以用注解@FunctionalInterface 检测是否为函数式接口
 
 第二章、怎么用Lambda
 
1.必须有一个函数式接口
看了第一章我们知道,Lambda表达式前面放普通接口是不行的,必须是Comparator 这种函数式接口。如图Collection接口不是函数式接口,报错了:

把Collection接口换成函数式接口Consumer 就可以复制运行了。
//Consumer 是函数式接口
Consumer con = (x) -> System. out .println(x);
        con.accept( "这个可以运行打印了" );2.省略规则
1. 参数类型必须同时省略
2. 一个参数时,参数的括号可省略
3. 代码块里只有一句时,可省略大括号,分号和return
Comparator com = (x, y) -> Integer.compare(10, 13);3.Lambda经常用来和匿名内部类比较
但注意:
1.Lambda表达式虽然简洁,用()->就可以代替整个匿名内部类,但只能用于函数式接口(有仅只有一个抽象方法的接口)。匿名内部类却可以用于接口,抽象类或者普通类。举个函数式接口Runnable接口的例子:
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("这是匿名内部类里传了个Runnable的实现类对象");
            }
        }).start();
    
用Lambda写一下
 new Thread(() -> System.out.println("好家伙这么简洁")).start();
第三章、具体使用举例()
我们要明确方法体才是关键所在,Lambda表达式方法体里的方法来自哪个函数式接口,这个接口的抽象方法作用是什么,才能有明确的目的去写Lambda表达式,也就是我们说的:“解决什么问题”。
1.案例一,自己写简单Lambda表达式(自定义的函数式接口)
1.自己写一个函数式接口注意只能有一个抽象方法,
public interface Test {
//有且仅有一个抽象方法
    public String TestFunc(String test_str);
}2.Lambda表达式:把字符串传入箭头符号右边的方法体
   Test test =(str)->{ System.out.println(str); return str;};
        String str=test.TestFunc("打印这个字符串");
        
   }2.案例二,Lambda表达式创建线程(Runnable函数式接口)
明确作用和方法:
1.Runnable接口,Runnable 为非 Thread 子类的类提供了一种激活方式。把Runnable的实例传给Thread 实例并将自身作为运行目标,就可以运行实现 Runnable 的类而无需创建 Thread 的子类。
唯一的抽象方法run()
使用实现接口Runnable的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的run方法
// 匿名内部 类
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名对象 传递线程任务.....");
            }
        }).start();2.再用Lambda表达式写
/*Lambda表达式 省略格式
1. 参数类型必须同时省略
2. 一个参数时,参数的括号可省略
3. 代码块里只有一句时,可省略大括号,分号和return  */
new Thread(() -> System.out.println("Lambda表达式 启动线程...")).start();3.案例三,Lambda表达式写判断型接口(Predicate函数式接口)
明确作用和方法:Predicate判断型接口,可以对数据进行条件的判断,返回判断的结果。
唯一抽象方法 boolean test(T t)
在给定的参数上进行条件评估。
演示:1.第一步先创建集合list
  //先创建一个集合
ArrayList<Integer> list = new ArrayList<>();
  //使用addAl方法添加元素
    Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9);2.用list调用removeIf()方法,
方法介绍: default boolean removeIf(Predicate<? super E> filter) ,删除集合中满足给定条件的元素
注意:因为removeIf()参数列表里需要传递的是函数式接口Predicate实例
所以我们可以在方法的括号里头,用上匿名内部类写法;在大括号里重写这个唯一的抽象方法。
 // 删除集合中的偶数  default boolean removeIf(Predicate<? super E> filter) 删除满足给定谓词的此集合的所有元素。
        list.removeIf(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer % 2 == 0;
            }
        });
        System.out.println(list);3.在前面我们提到Predicate接口是函数式接口,所以我们自然可以用Lambda重写一次
//不省略格式
    list.removeIf( (Integer itgr) -> { return itgr % 2 == 0;});
//省略写法 
// 1.一个参数把括号和参数类型     省略
// 2.只有一条方法语句把大括号{}和; return 省略
    list.removeIf(  itgr -> itgr % 2 == 0);
//打印集合
    System.out.println(list);4.案例四,Lambda表达式写比较器(Comparator函数式接口)
明确作用和方法:Comparator函数式接口,强行对某个对象 collection 进行整体排序 的比较函数。可以将 Comparator实例 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
唯一的抽象方法
compare(T o1, T o2)
比较用来排序的两个参数
演示:
1.创建集合加入元素
 // 创建集合使用addAll()方法加入元素
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1, 3, 2, 4, 5, 7, 9, 8, 6);
        // 先用sort(list)方法进行  升序 排序
        Collections.sort(list);
        System.out.println(list);2.注意:因为参数列表里需要传递的参数类型是函数式接口Comparator
所以我们可以在sort()方法的括号里头,用上匿名内部类写法;在里头重写这个唯一的抽象方法compare()
//匿名内部类  写降序排序,Collections.sort(List<T> list, Comparator<? super T> c)
        
Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
      3.用Lambda重写一下
//lambda表达式写 降序排序
// Collections.sort(list,(Integer o1, Integer o2)->{ return o2 - o1;});
// 简化格式,两个参数类型一样省略参数类型但是括号不能省略,方法体只一条语句省略{};return
    Collections.sort(list,(o1,o2)->  o2 - o1);
     System.out.println(list);5.案例五,Lambda表达式写过滤器(FileFilter函数式接口)
明确作用和方法:抽象路径名的过滤器。该接口的实例可以传递给FilelistFiles(FileFilter)
FileFilter接口的唯一抽象方法accept(File pathname)
测试指定的抽象路径名是否应包含在路径名列表中。
类的listFiles(FileFilter filter)方法介绍:File返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。
演示1:
1.先用匿名内部类写
 // 创建文件对象,文件路径是d:\\demo
        File file = new File("d:\\demo");
        // file调用listFiles()直接传入过滤器的实例和pathname,返回类型是数组
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                //endsWith(".txt") 获取以.txt结尾,并且只要是文件,
                return pathname.getName().endsWith(".txt") && pathname.isFile();
            }
        });2.用Lambda写
//这是未简化
File[] files1 = file.listFiles((File pathname)->{return pathname.isFile() && pathname.getName().endsWith(".txt");});
//简化格式后
        File[] files1 = file.listFiles( pathname -> pathname.isFile() && pathname.getName().endsWith(".txt") );


















