//函数式接口:有且仅有一个抽象方法的接口(可以有其他类型方法),
// 适用于函数式编程--》lamdba表达式
// 语法糖:指更加方便但是底层原理不变的代码语法(for-each为迭代器的语法)
// lamdba表达式可以“当作”匿名内部类的语法糖,但是其实原理不同, lamdba表达式不会创建.class文件
// 而匿名内部类是内部类的一种,其使用会创建.class文件
// 定义:注解@FunctionalInterface
// 使用:作为方法的参数与返回值类型(用 接口实现类,匿名内部类,lamdba表达式 传参)
// 应用:性能浪费的日志事例 问题:方法参数先拼接 字符串后调用方法 如果不满足条件,不打印,还是会先拼接 还是会拼接【浪费】
// 解决:用lamdba表达式的延迟加载 定义一个拼接的抽象方法(函数式接口中)
// lamdba表达式使用前提:必须有函数式接口 Lanmdba表达式的省略中 return关键字省略,其后面return的内容可以不省略
// Runnable/Comparator都是函数式接口
// 一个方法返回值是comparator或comparable接口,其就可以作为sort等方法的比较器 返回值是其他接口也一样类比
// 是同接口效果一样的; 方法中对于接口抽象方法的重写可以使用匿名内部类/拉美的吧表达式等简写代码
// 使用函数式接口的方法一般参数类型是 函数式接口+要处理的数据的类型 返回值是自己想要得到的返回值类型
// (一般是对于函数式接口的抽象方法返回值类型 或 对其在方法内操作后的类型)
// 常用的函数式接口:java.until.Function包中
// 为什么用函数式接口:设计时笼统设计,将方法的实现由定义转到传参调用时,并且调用时可以使用方法外的东西(用lamdba表达式)
// 为什么用函数式接口:好处是你不用单独为了一小段代码再撰写一个类
// (当然函数式接口使用过的是匿名内部类,本质上也是创建了类的,只不过不用撰写类放在项目目录下),
// 这样可以提高开发效率,当然可读性比直接撰写了差一些
// Supplier
// 应用:获取int数组的最大值并返回
// Consumer
// 默认方法 default Consumer
// con1.andThen(con2).accept(。。) 谁在前,谁就先消费
// 应用 :格式打印 姓名:xxx。年龄:xxx。
// Predicate
// 默认方法 and 方法使用同andThen 逻辑与 底层与使用同 &&逻辑运算符
// or方法《==》 ||逻辑运算符
// negat方法《==》 !逻辑运算符
// 应用:对姓名+性别的字符串进行筛选 满足必须为女且姓名为4个字 加入arraylist集合中返回
// Function
// 默认方法:andThen方法
// 应用:将String转为Integer 转化后加10 再转为String类型
// 用Function接口进行函数模型的拼接 对于一个包含姓名年龄的字符串进行
// 截取年龄字符串《String,String》 将字符串转为int《String,Integer》 int加100《Integer,Integer》
//lambda表达式衍生物 Stream
// 应用:将集合/数组转为Stream流 解决集合/数组的弊端
// 将集合的循环遍历优化,遍历是每一个输出,循环是输出从头到尾的输出方式
// 原理:JDK1.8后才有,函数式编程思想,关注做什么,而不是怎么做 底层是队列
// 使用:Stream流不会存储,相当于工厂流水线 ,
// 而且有lambda表达式的延迟执行,只有最后一部分结束,其才会执行整个流程
// 特征:1 pipelinig 中间操作返回都还是这个流
// 2 内部迭代 流可以直接在内部调用遍历方法 不同于使用for循环的外部迭代
// Stream
// 可能会出问题,所以最好加上泛型
// 静态方法 of方法与concat方法 用时不要加上泛型
// 获取流:Collection集合都可以使用接口默认方法 stream获取
// 用stream接口的静态方法 of 获取
// Map可以转为(keyset键,values值,entryset键值对映射关系) set集合获取
// 数组用of方法获取
// 方法: 延迟方法:返回自身 可链式编程
// 终结方法,返回其他 终结方法不能用多个
// 遍历方法:void foreach(Consumer con)终结方法,用于遍历流中数据
// 过滤方法:stream filter(Predicate pr)延迟方法,保留Predicate中抽象方法返回true的数据
// 映射方法:stream map(Function fc) 延迟方法 将流中数据类型改变返回
// 统计个数:long count() 终结方法 统计元素个数
// 取前n个: stream limit (long n) 延迟方法 将当前集合取前n个 一共没有取得多,会返回所有元素
// 跳过前n个:stream skip(long n) 跳过长度大于等于流中数据长度,返回空流
// 组合流数据:静态方法:static stream concat(stream a,stream b) 合并两个流 注意不能合并被用过的流
// 特点:stream属于管道流,只能被消费(使用)一次 stream用延迟方法传给一个新的stream流,旧的就会被关闭,不能再用了
//方法的引用:是对于lambda表达式的简化 ::双冒号是引用运算符
// 使用:lambda表达式的方法体调用的方法,存在于某一对象中,可用方法引用再次简化
// 注意lambda传递的参数一定要是方法引用 引用的那个方法可以接收的类型,否则会抛出异常
// 引用:lambda表达式的重写方法中
// 通过对象名引用成员方法(应用类中)
// 通过super引用父类成员方法(子类中)
// 通过类名引用静态成员方法(应用类中)
// 通过this引用本类成员方法(注意这个不能在静态方法中使用,因为静态不能用this)
// 类的构造器(构造方法)引用: 类名称::new 应用:数组的构造器引用