Java8中有两个最为重要的改变.第一个是Lambda表达式;另外一个是Stream API
JDK8函数式接口定义:接口中只有一个抽象方法,可以有默认实现方法和静态已实现的方法.
1.Lambda表达式
1.1)初识Lambda表达式和Stream API
看下图例子
优化方式:策略模式--->定义接口,写抽象方法 上面三个方法不就是返回一个boolean么
然后只写一个过滤方法filterEmp(需要比较的集合,过滤的实现类)
以后需要过滤什么,至少方法体不用动了,只要加接口就行了,比如需要过滤工资大于5000的就加个过滤5000是实现类
但想想需要加这么多实现类么?? 不能用匿名内部类么
再用Lambda简写
java8中,连MyPredicate这个接口都不需要你写,已经定义好了
那么方法改一下
甚至可以这么写 Stream API
如果需求是查出工资大于5000并且取两个
如果需求是查出所有员工名字
1.2)Lambda表达式基础语法
Lambda表达式需要函数式接口的支持:接口中只有一个抽象方法(该接口就是函数式接口)
可以使用@FunctionalInterface注解,该注解可以声明检查强制规定只能有一个接口
类型推断
1.3Lambda表达式练习
1.调用Collections.sort()方法,通过定制排序比较两个Emp(先按年龄比,年龄相同按姓名比),使用Lambda表达式做为参数传递
2.1)申明函数式接口MyFun,接口中声明抽象方法:public String getValue(String str)
2.2) 声明类TestLambda3,类中编写方法使用接口做为参数,将一个字符串转换成大写,并作为方法的返回值
2.3) 再将一个字符串的第2个和第4个索引位置进行截取子串
3.1) 声明一个带两个泛型的函数式接口,泛型类型为<T,R> T作为参数,R作为返回值
3.2) 在接口中声明对应抽象方法
3.3) 在TestLambda3类中声明方法,使用接口作为参数,计算两个Long型参数的和.
3.4) 再计算两个Long型参数的乘积
1.4)通过行为参数化传递代码
软件工程中一个众所周知的问题:不管不你做什么,用户的需求肯定会变.比方说,有个应用程序是帮助农夫了解自己的库存.第一天,他需要一个查找库存中所有绿色苹果的功能;第二天,可能需要一个查找重量超过150克苹果的功能;第三天需要一个查找所有颜色是绿色且重量超过150克的苹果库存.
行为参数化就是可以处理频繁变更需求的一种软件开发模式.
以上例子,都在用行为参数化进行代码传递
只是对员工的比较,能不能将员工进行抽象化呢????????
如果我这么干????会不会更好
行为参数化就是一个方法接受多个不同的行为作为参数,并在内部使用他们,完成不同行为的能力.
2.函数式接口(四大内置核心函数式接口)
2.1) Consumer<T>:消费型接口
参数类型:T 返回类型:void
作用:对类型为T的对象应用操作,包含方法 void accept(T t)
2.2) Supplier<T>:供给型接口
参数类型:无 返回类型:T
作用:返回类型为T的对象,包含方法 T get()
2.3) Function<T,R>:函数型接口
参数类型:T 返回类型:R
作用:对类型为T的对象应用操作,并返回结果.结果是R类型的对象.包含方法 R apply(T t)
就是对T进行一顿猛烈操作后输出R,这个叫做Function<T,R>
2.4) Predicate<T>:断言型接口
参数类型:T 返回类型:boolean
作用:确定类型为T的对象是否满足某约束,并返回boolean值.包含方法 boolean test(T t)
3.方法引用和构造引用
3.1)方法引用:
若Lambda 体中的内容有方法已经实现了,我们可以使用"方法引用"
可以理解为"方法引用"是Lambda 表达式的另外一种表现形式
方法引用主要有三种语法格式
对象::实例方法名
要求接口中的参数列表和返回值类型与实例方法的参数列表和返回值类型一致
类::静态方法名
要求接口中的参数列表和返回值类型与实例方法的参数列表和返回值类型一致
类::实例方法名
第一个参数是实例方法的调用者,第二个参数是实例方法的参数时(可以没有第二个参数)
3.2)构造器引用
ClassName::new
接口方法与构造器方法参数列表类型一致
下是调用了无参构造
3.3)数组引用
Type::new
4.Stream API
java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找,过滤和映射数据等操作.使用Stream API对集合数据进行操作,就类似于使用SQL执行数据库查询.也可以使用Stream API来并行执行操作.简而言之,Stream API提供了一种高效且易于使用的处理数据的方式
"集合讲的是数据,Stream流讲的是计算"
流是java8引入的新成员,简单讲就是对集合数组等进行一系列操作,生成一个新的集合数组,对原来的集合数组无影响
1.Stream 自己不会存储元素
2.Stream的中间操作不会改变源对象.会返回一个持有结果的新Stream(比如Stream的筛选,切片,映射,排序,查找,匹配,归约收集)
3.Stream 操作时延迟执行的.这意味着他们会等到需要结果的时候才执行(foreach(),toArray()等属于终端操作,终端操作有可能影响源数据)
Stream操作的三个步骤:
4.1.创建 Stream:一个数据源(如:集合,数组),获取一个流 4种方式
4.2.中间操作:一个中间操作链,对数据源的数据进行处理
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理而是在终止操作时一次性全部处理,称为"惰性求职"
4.2.1)Stream赛选与切片
1.filter(Predicate p):接收Lambda,从流种排除某些元素
2.limit(long maxSize):截断流,使其元素不超过给定数量
3.skip(long n):跳过元素,返回一个扔掉了前n个元素的流.若流中元素不足n个,则返回一个空流,与limit(n)互补 skip是扔掉前面n个取后面 limit是取前面n个
4.distnct():筛选,通过流所生成元素的 hashCode()和equals()去除重复元素
4.2.2)Stream映射
1.map(Function f):接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
2.flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流.
先看个例子
3.mapToDouble(ToDoubleFunction f):接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStream.
4.mapToInt(ToIntFunction f):接收一个函数作为参数,该参数会被应用到每个元素上,产生一个新的IntStream.
5.mapToLong(ToLongFunction f):接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的LongStream.
4.2.3)Stream排序
1.sorted():产生一个新流,其中按自然顺序排序
2.sorted(Comparator):产生一个心流,其中按比较器顺序排序
4.3.终止操作(终端操作):一个终止操作,执行中间操作链,并产生结果(一个或多个结果)
4.3.1)Stream查找与匹配
1.allMatch(Predicate p):检查是否匹配所有元素
2.anyMath(Predicate p): 检查是否至少匹配一个元素
3.noneMatch(Predicate p):检查是否没有匹配所有元素
4.findFirst():返回第一个元素
5.findAny():返回当前流中的任意元素
6.count:返回流中元素的总个数
7.max:返回流中最大值
8.min:返回流中最小值
4.3.2)Stream归纳
1.reduce(T identity,BinaryOperator)/reduce(BinaryOperator)--可以将流中元素反复结合起来,得到一个值
4.3.3)Stream收集
1.collect--将流转换为其他形式.接收一个Collector接口实现,用于给Stream中元素做汇总的方法
4.3.4)Stream练习
4.4.并行流与顺序流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流
Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以通过parallel()和sequential()在并行流与顺序流之间进行切换
5.Optional容器
Optional类
Optional<T>类是一个容器类,代表一个值存在或者不存在,原来用null表示一个值不存在,现在Optional可以更好的表达这个概念.并且可以避免空指针异常.
常用方法:
Optional.of(T t):创建一个Optional实例
Optional.empty():创建一个空的Optional实例
空的Optional去get报错
Optional.ofNullable(T t):若t不为null,创建Optional实例,否则创建空实例
isPresent():判断是否包含值
orElse(T t):如果调用对象包含值,则返回该值,否则返回t
orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回s获取的值
map(Function f):如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
flatMap(Function mapper):与map类似,要求返回值必须是Optional
6.接口中的默认方法和静态方法
Java8开始接口中除了抽象方法外,还可以有default修饰的默认实现方法和staic修饰的静态实现方法