01.第一章：函数式接口_概念及格式：
	1).什么是“函数式接口”：有且只有一个抽象方法的接口。(可以包含其他默认方法、静态方法、私有方法...)
	2).定义格式：
		访问修饰符(public/默认)  interfae 接口名{
			void show();//默认：public abstract void show();
		}
02.第一章：函数式接口_@FunctionalInterface注解：
	1).我们可能要经常需要定义：函数式接口，为了可以使用Lambda表达式。
	2).为了避免定义时发生语法错误，可以使用@FunctionalInterface注解来强制编译器检查。这个注解类似于：@Override注解。
	3).示例代码：
		@FunctionalInterface
		public interface IA{
			public void show();
			public void show1();//编译错误
		}
03.第一章：函数式接口_练习_自定义函数式接口(无参无返回值)：
interface Usb{
    public void run();
}

class Keyboard implements Usb {
    @Override
    public void run() {
        System.out.println("键盘开始工作....");
    }
}
public class Demo {
    public static void main(String[] args) {
        //1.方式一：传递子类对象
        computer(new Keyboard());
        //2.方式二：传递匿名内部类对象
        computer(new Usb(){
            @Override
            public void run() {
                System.out.println("鼠标开始工作....");
            }
        });
        //3.方式三：使用Lambda表达式
        computer(()->System.out.println("音响开始响起...."));
    }

    public static void computer(Usb usb) {
        usb.run();
    }
}

04.第一章：函数式接口_练习_自定义函数式接口(有参有返回值)：
interface IA{
    public int calc(int a, int b);
}
public class Demo {
    public static void main(String[] args) {
        //1.匿名子类对象
        fun(new IA() {
            @Override
            public int calc(int a, int b) {
                return a + b;
            }
        }, 10, 20);

        //2.Lambda表达式
        fun((int a ,int b)->{return a + b;},100,200);

    }
    public static void fun(IA a,int x,int y){
        System.out.println("结果是：" + a.calc(x,y));
    }
}

-------------------------------------------------------------------------
05.第二章：函数式编程_Lambda的应用_延迟执行：
	1).未延迟：
public class Demo {
    public static void main(String[] args) {
        String s1 = "日期:2018-08-27";
        String s2 = "异常：学员分数错误";
        String s3 = "位置：Demo.java 12";

        writeLog(2,s1 + s2 + s3);//效率比较低
    }

    public static void writeLog(int level, String msg) {
        if (level == 1) {
            System.out.println(msg);
        }
    }
}
	2).延迟：
		
interface MessageBuilder{
    public String buildMsg();
}
public class Demo {
    public static void main(String[] args) {
        String s1 = "日期:2018-08-27";
        String s2 = "异常：学员分数错误";
        String s3 = "位置：Demo.java 12";

        writeLog(1,()-> s1 + s2 + s3);//s1 + s2 + s3这段代码只有在leve == 1时才会被执行
    }

    public static void writeLog(int level, MessageBuilder mb) {
        if (level == 1) {
            System.out.println(mb.buildMsg());//只有当条件满足，才调用buildMsg()方法-->Lambda表达式
        }
    }
}

06.第二章：函数式编程_Lambda的应用_已有的接口使用Lambda作为形参和返回值：
public class Demo {
    public static void main(String[] args) {
	//测试Lambda返回值
        Runnable run = getRun();
        new Thread(run).start();
	//测试Lambda形参
        setRun(() -> System.out.println("参数Lambda线程开始运行..."));
    }
    //Lambda做返回值
    public static Runnable getRun(){
        //匿名内部类对象
        /*return new Runnable(){
            @Override
            public void run() {
                System.out.println("匿名子类线程对象开始运行....");
            }
        };*/
        //使用Lambda表达式
        return () -> System.out.println("Lambda线程开始运行....");
    }
    //Lambda做参数
    public static void setRun(Runnable run) {
        new Thread(run).start();
    }
}

07.第二章：函数式编程_练习_自定义接口使用Lambda作为参数和返回值：
interface IA{
    public void show();
}
public class Demo {
    public static void main(String[] args) {
        IA a = getIa();
        a.show();
        //测试形参
        setIa(()-> System.out.println("我爱Java..."));
    }
    //返回值
    public static IA getIa(){
        return ()->System.out.println("HelloWorld");
    }

    //做形参
    public static void setIa(IA ia) {
        ia.show();
    }
}
-------------------------------------------------------------------------
08.第三章：方法引用_使用自定义静态方法替代Lambda：
interface IA{
    public void show();
}
public class Demo {
    public static void main(String[] args) {
//        fun1(()-> System.out.println("呵呵..."));
        fun1(Demo :: method);
    }

    private static void fun1(IA a) {
        a.show();
    }

    public static void method(){
        System.out.println("呵呵...");
    }
}

09.第三章：方法引用_使用类库静态方法替代Lambda：
interface IA{
    public String printArray(int[] arr);
}
public class Demo {
    public static void main(String[] args) {
        int[] arr = {1, 43, 2, 52, 432, 5, 24312, 43, 52, 432};
        //使用Lambda表达式
        /*prtArray((int[] array)->{
            StringBuilder bld = new StringBuilder("[");
            for (int i = 0; i < array.length; i++) {
                bld.append(array[i]);
                if (i < array.length - 1) {
                    bld.append(" ,");
                }else{
                    bld.append("]");
                }
            }
           return bld.toString();
        },arr);*/
	
        //使用Arrays类的toString()方法代替
        //类库中有一个方法可以打印一个int[]数组：Arrays类的toString()方法
        //所以，我们如果也想实现打印一个数组，那么可以使用这个方法来代替
        prtArray(Arrays::toString,arr);
    }

    private static void prtArray(IA a ,int[] arr) {
        System.out.println(a.printArray(arr));
    }
}

10.第三章：方法引用_替代原则：
	1).我们可以使用任意的方法--只要其形参和返回值同接口的抽象方法一致，
	   就可以使用这个方法替换Lambda。
11.第三章：方法引用_使用对象成员方法引用替代Lambda
interface IGame{
    public void run();
}
class Student{
    public void playGame(IGame game) {
        game.run();
    }
}
class Teacher{
    public void tea(){
        System.out.println("我爱喝茶，红茶，绿茶.....");
    }
}
public class Demo {
    public static void main(String[] args) {
        Student stu = new Student();
//        stu.playGame(()-> System.out.println("王者荣耀启动...."));
        //使用Teacher对象的tea()方法替换game.run
        Teacher t = new Teacher();
        stu.playGame(new Teacher()::tea);
    }
}

12.第三章：方法引用_使用super父类方法替代Lambda：
interface IGame{
    public void run();
}
class Fu{
    public void like(){
        System.out.println("我喜欢喝啤酒....");
    }
}
class Student extends Fu{
    public void playGame(IGame game) {
        game.run();
    }

    public void like() {
      // playGame(()-> System.out.println("我喜欢喝啤酒..."));
        //使用父类的like方法
      //  playGame(()-> super.like());
          playGame(super::like);
    }
}

public class Demo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.like();
    }
}
13.第三章：方法引用_使用this本类方法替代Lambda：
interface IGame{
    public void run();
}

class Student{
    public void playGame(IGame game) {
        game.run();
    }

    public void like() {
//         playGame(()-> System.out.println("我每天都坚持跑10公里..."));
        playGame(this::running);
    }

    public void running(){
        System.out.println("我每天坚持跑10公里....");
    }
}

public class Demo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.like();
    }
}

14.第三章：方法引用_类的构造器引用：
		1).无参的：
class Cat{
    public void show(){
        System.out.println("我是小猫喵喵喵....");
    }
}

interface CatFactory{
    public Cat getCat();
}
public class Demo {
    public static void main(String[] args) {
        //使用匿名内部类：
        /*get(new CatFactory() {
            @Override
            public Cat getCat() {
                return new Cat();
            }
        });*/
        //使用Lambda
//        get(() -> new Cat());
        //使用构造器引用
        get(Cat::new);

    }
    public static void get(CatFactory cf){
        Cat c = cf.getCat();
        c.show();
    }
}
		2).有参的：
class Cat{
    private String name;

    public Cat(String name) {
        this.name = name;
    }
    public void show(){
        System.out.println("我是小猫:" + name);
    }
}

interface CatFactory{
    public Cat getCat(String name);
}
public class Demo {
    public static void main(String[] args) {
        //使用匿名内部类：
        /*get(new CatFactory() {
            @Override
            public Cat getCat(String name) {
                return new Cat(name);
            }
        });*/
        //使用Lambda
//        get((s) -> new Cat(s));
        //使用构造器引用
        get(Cat::new,"花花");

    }
    public static void get(CatFactory cf,String name){
        Cat c = cf.getCat(name);
        c.show();
    }
}

15.第三章：方法引用_数组构造器引用：
interface IA{
    public int[] makeArray(int len);
}
public class Demo {
    public static void main(String[] args) {
        //1.匿名内部类的方式：
        fun(new IA(){
            @Override
            public int[] makeArray(int len) {
                return new int[len];
            }
        },10);
        //2.Lambda表达式
        fun((int len) -> new int[len], 20);
        
        //3.数组构造器引用
        fun(int[]::new, 200);
        
    }

    private static void fun(IA a, int length) {
        int[] arr = a.makeArray(length);
        System.out.println("数组长度：" + arr.length);
    }
}

------------------------------------------------------------------
16.第四章：常用函数式接口_生产接口_Supplier接口：
public class Demo {
    public static void main(String[] args) {
        f1(() -> "Hello");
        f1(() -> "World");

        f2(() -> 10);
        f2(() -> 100);

    }

    public static void f1(Supplier<String> stringSupplier) {
        System.out.println(stringSupplier.get());//打印：String
    }

    public static void f2(Supplier<Integer> supplier) {
        System.out.println(supplier.get());//打印：Integer
    }
}

17.第四章：常用函数式接口_消费接口_Consumer接口_抽象方法accept：
public class Demo {
    public static void main(String[] args) {
        c1((s) -> System.out.println(s),"Hello");
        c2((n) -> System.out.println(n), 100);

    }

    public static void c1(Consumer<String> c, String s) {
        c.accept(s);
    }

    public static void c2(Consumer<Integer> c, Integer integer) {
        c.accept(integer);
    }
}

18.第四章：常用函数式接口_Consumer接口_默认方法andThen：

public class Demo {

    public static void main(String[ ] args) {
        consumeString(
                s -> System. out. println(s. toUpperCase()) ,
                s -> System. out. println(s. toLowerCase())) ;
    }

    private static void consumeString(Consumer<String> one,
                                            Consumer<String> two) {
       // one.andThen(two).accept("Hello") ;

        new Consumer<String>(){
            @Override
            public void accept(String s) {
                one.accept(s);
                two.accept(s);
            }
        }.accept("Hello");
    }
}

=================================================================
学习目标总结：
01.能够使用@FunctionalInterface注解
	@FunctionalInterface
	interface IA{
		public void show();
	}
02.能够自定义无参无返回函数式接口
	interface IA{
		public void show();
	}
03.能够自定义有参有返回函数式接口
	interface IA{
		public int calc(int a,int b);
	}
	public class Demo{
		public static void main(String[] args){	
			f1((m,n) -> m + n,10,20);
		}
		public static void f1(IA a,int x,int y){
			System.out.println(a.calc(x,y));
		}
	}
04.能够理解Lambda延迟执行的特点
interface MessageBuilder{
    public String buildMsg();
}
public class Demo {
    public static void main(String[] args) {
        String s1 = "日期:2018-08-27";
        String s2 = "异常：学员分数错误";
        String s3 = "位置：Demo.java 12";

        writeLog(1,()-> s1 + s2 + s3);//s1 + s2 + s3这段代码只有在leve == 1时才会被执行
    }

    public static void writeLog(int level, MessageBuilder mb) {
        if (level == 1) {
            System.out.println(mb.buildMsg());//只有当条件满足，才调用buildMsg()方法-->Lambda表达式
        }
    }
}

05.能够使用Lambda作为方法的参数
	public static void main(String[] args){
		setRunnable(()->System.out.println("Lambda线程启动"));
	}
	public static void setRunnable(Runnable r){
		new Thread(r).start();
	}
06.能够使用Lambda作为方法的返回值
	public static void main(String[] args){
		Runnable r = getRunnable();
		new Thread(r).start();
	}
	public static Runnable getRunnable(){
		return ()->System.out.println("Lambda的线程启动");
	}
07.能够使用输出语句的方法引用
	interface IA{
		public void show(String s);
	}
	public static void main(String[] args){
		//1.使用Lambda
		f1((s)->System.out.println(s),"Hello");
		//2.使用类库中的方法替换
		f1(System.out::println,"Hello");
	}
	public static void f1(IA a,String s){
		a.show(s);
	}
08.能够通过4种方式使用方法引用
	1).类名引用：
		(类名::静态方法)
	2).对象名引用：
		(new 对象()::成员方法)
	3).super引用：
		在子类中：
		super::父类的方法名
	4).this引用：
		this::本类的方法名
	5).构造器引用：
		Cat::new
	6).数组引用：
		int[]::new
09.能够使用类和数组的构造器引用
	
10.能够使用Supplier函数式接口：生产接口
	
public class Demo {
    public static void main(String[] args) {
        f1(() -> "Hello");
        f1(() -> "World");

        f2(() -> 10);
        f2(() -> 100);

    }

    public static void f1(Supplier<String> stringSupplier) {
        System.out.println(stringSupplier.get());//打印：String
    }

    public static void f2(Supplier<Integer> supplier) {
        System.out.println(supplier.get());//打印：Integer
    }
}

11.能够使用Consumer函数式接口：消费接口
public class Demo {
    public static void main(String[] args) {
        c1((s) -> System.out.println(s),"Hello");
        c2((n) -> System.out.println(n), 100);

    }

    public static void c1(Consumer<String> c, String s) {
        c.accept(s);
    }

    public static void c2(Consumer<Integer> c, Integer integer) {
        c.accept(integer);
    }
}