Java8新特性的学习
1. Lambda表达式
Lambda是一个匿名函数,我们可以把Lambda表达式理解为一段可传递的代码(将代码像数据一样进行传递),可写出更简洁,更灵活的代码,使JAVA语言表达能力得到了提升。
- Lambda表达式引入了一个 叫箭头操作符或Lambda操作符 ->
- Lambda表达式 拆分成两部分 :
- 左侧: Lambda表达式的参数列表
- 右侧:Lambda表达式中所需执行的功能 即Lambda体
2.方法引用
若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可理解为方法引用是Lambda表达式的另一种表现形式)
主要有三种语法格式:
①注意:Lambda体中调用方法的参数列表与返回值类型,要与函数式接口的参数列表 返回值类型一致!
2.1. 语法一 ( 对象::实例方法 )
Consumer< String> con = ( x) - > System. out. println ( x) ;
Consumer< String> con = System. out: : println;
con. accept ( "你好贱" ) ;
Emp emp = new Emp ( ) ;
Supplier< String> supplier = ( ) - > emp. getName ( ) ;
Supplier< String> supplier = emp: : getName;
System. out. println ( supplier. get ( ) ) ;
2.2.语法二 ( 类::静态方法 )
Comparator< Integer> com = ( x, y) - > Integer. compare ( x, y) ;
Comparator< Integer> com = Integer: : compare;
int num = com. compare ( 4 , 2 ) ;
System. out. println ( num) ;
2.3.语法三 ( 类::实例方法 )
②注意:对于语法三格式有特殊要求 若Lambda参数列表第一个参数是 调用该实例方法的调用对象 而第二个参数是是实例方法的参数列表参数 可以使用此格式
BiPredicate< String, String> bp = ( x, y) - > x. equals ( y) ;
BiPredicate< String, String> bp = String: : equals;
System. out. println ( bp. test ( "打架机" , "打架机" ) ) ;
2.4语法四(ClassName::new)
Supplier< Emp> supplier = ( ) - > new Emp ( ) ;
Supplier< Emp> supplier2 = Emp: : new ;
System. out. println ( supplier2. get ( ) ) ;
Function< String, Emp> function = ( str) - > new Emp ( str) ;
Function< String, Emp> function1 = Emp: : new ;
System. out. println ( function1. apply ( "黎智健" ) ) ;
BiFunction< String, Integer, Emp> biFunction = Emp: : new ;
System. out. println ( biFunction. apply ( "黎智健" , 28 ) ) ;
2.5语法五(Type[]::new)
Function< Integer, String[ ] > function = ( num) - > new String [ num] ;
Function< Integer, String[ ] > function1 = String[ ] : : new ;
System. out. println ( function1. apply ( 10 ) . length) ;
3. JAVA8内置四大核心函数式接口
接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解@FunctionalInterface 修饰 此注解可检查接口是否为 函数式接口
3.1 Consumer ---- 消费型接口
void accept(T t);
@Test
public void test ( ) {
happy ( 2000 , ( m) - > System. out. println ( "我消费了" + m+ "美元" ) ) ;
}
public void happy ( double money, Consumer< Double> consumer) {
consumer. accept ( money) ;
}
3.2.Supplier ---- 供给型接口
T get();
@Test
public void test1 ( ) {
List< Integer> list = randomCreateNumByInterface ( 10 , ( ) - > ( int ) ( Math. random ( ) * 100 ) ) ;
list. forEach ( System. out: : println) ;
}
public List< Integer> randomCreateNumByInterface ( int num , Supplier< Integer> supplier) {
List< Integer> lists = new ArrayList < > ( ) ;
for ( int i = 0 ; i < num; i++ ) {
lists. add ( supplier. get ( ) ) ;
}
return lists;
}
3.3 Function<T,R> ---- 函数型接口
R apply(T t);
@Test
public void test2 ( ) {
String trimStr = solveStr ( "\t\t\t\t\t帮我去掉空格" , ( str) - > str. trim ( ) ) ;
String subStr1 = solveStr ( "帮我截取一段其中的一段文字" , ( str) - > str. substring ( 0 , 3 ) ) ;
System. out. println ( trimStr) ;
System. out. println ( subStr1) ;
}
public String solveStr ( String str , Function< String, String> function) {
return function. apply ( str) ;
}
3.4 Predicate 断言型接口
boolean test(T t);
@Test
public void test3 ( ) {
List< String> lists = Arrays. asList ( "范德萨发生" , "胜多负少" , "防守打法" , "认为如果" ) ;
List< String> templist = filter ( lists, ( str) - > str. length ( ) > 4 ) ;
templist. forEach ( System. out: : println) ;
}
public List< String> filter ( List< String> list, Predicate< String> predicate) {
List< String> temp = new ArrayList < > ( ) ;
for ( String str : list) {
if ( predicate. test ( str) ) {
temp. add ( str) ;
}
}
return temp;
}
3.5其他的函数式接口
4.Stream API
4.1流是什么?
是数据渠道,用于操作数据源(集合,数组等)所产生的元素序列。
集合讲的是数据,流讲的是计算
注意
①Stream自己不会存储元素的
②Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream
③Stream操作是延迟执行的,这意味他们会等到需要结果的时候才执行
4.2Stream的操作的三个步骤
一个数据源(如 集合、数组),获取一个流
一个中间操作链,对数据源的数据进行处理
一个终止操作,执行中间操作链,并产生结果
1.创建流
可通过Collection集合提供的 stream()/串行流 和 parallelStream()/平行流创建流
List< String> lists = new ArrayList < > ( ) ;
Stream< String> stream = lists. stream ( ) ;
Stream< String> parallelStream = lists. parallelStream ( ) ;
通过Arrays 中的静态方法 stream() 获取数组流
Emp [ ] emparr = new Emp [ 10 ] ;
Stream< Emp> stream1 = Arrays. stream ( emparr) ;
通过Stream类静态方法of()
Stream< String> stream3 = Stream. of ( "abf" , "gdu" , "tew" ) ;
创建无限流 / 迭代
Stream< Integer> iterate = Stream. iterate ( 0 , ( x) - > x+ 2 ) ;
iterate. limit ( 10 ) . forEach ( System. out: : println) ;
创建无限流 / 生成
Stream. generate ( ( ) - > Math. random ( ) ) . limit ( 20 ) . forEach ( System. out: : println) ;
2.中间操作
筛选与切片
方法名 作用 filter 接受Lambda,从流中排除某种元素 limit 截断流,使其流不超过给定数量 skip(n) 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流, 【与limit(n) 互补】 distinct 筛选,通过流所生成元素的hashCode() 和 equals() 去除重复元素
1.f ilter
Stream< Emp> filter = emps. stream ( ) . filter ( ( e) - > e. getAge ( ) > 18 ) ;
filter. forEach ( System. out: : println) ;
补充:上边提到的 ‘延迟加载’ 多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为‘惰性求值’
Stream< Emp> filter = emps. stream ( ) . filter ( ( e) - > {
System. out. println ( "延迟加载。。。。" ) ;
return e. getAge ( ) > 18 ;
} ) ;
filter. forEach ( System. out: : println) ;
注意:①找到满足条件的数据的指定条数 就不往下迭代。
2. limit
Stream< Emp> filter = emps. stream ( ) . filter ( ( e) - > e. getAge ( ) > 18 ) ;
filter. limit ( 1 ) . forEach ( System. out: : println) ;
3. skip
Stream< Emp> filter = emps. stream ( ) . filter ( ( e) - > e. getAge ( ) > 18 ) ;
filter. skip ( 2 ) . forEach ( System. out: : println) ;
映射
方法名 作用 map 接受Lambda,将元素转换成其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的对象 flatMap 接受一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流这两个区别就是当提取的是一个 流对象 map只能在流对象 装 提取出的流对象 而 flatMap可以将提取的所有流对象 变为一个流对象和add() addAll() 很像
1. map
Stream< Emp> map = emps. stream ( ) . map ( ( emp) - > { emp. setAge ( 12 ) ; return emp; } ) ;
map. forEach ( System. out: : println) ;
List< String> asList = Arrays. asList ( "wreew" , "dfa" , "sdfs" , "sdfs" ) ;
Stream< String> map2 = asList. stream ( ) . map ( ( x) - > x. toUpperCase ( ) ) ;
map2. forEach ( System. out: : println) ;
emps. stream ( ) . map ( Emp: : getName) . forEach ( System. out: : println) ;
1. map
List< String> asList = Arrays. asList ( "wreew" , "dfa" , "sdfs" , "sdfs" ) ;
Stream< Stream< Character> > map = asList. stream ( ) . map ( TestStreamAPI2: : fileterToCharacter) ;
map. forEach ( ( stream) - > stream. forEach ( System. out: : println) ) ;
public static Stream< Character> fileterToCharacter ( String str) {
List< Character> lists = new ArrayList < Character> ( ) ;
for ( char c : str. toCharArray ( ) ) {
lists. add ( c) ;
}
return lists. stream ( ) ;
}
2.f latmap
List< String> asList = Arrays. asList ( "wreew" , "dfa" , "sdfs" , "sdfs" ) ;
Stream< Character> flatMap = asList. stream ( ) . flatMap ( TestStreamAPI2: : fileterToCharacter) ;
flatMap. forEach ( System. out: : println) ;
public static Stream< Character> fileterToCharacter ( String str) {
List< Character> lists = new ArrayList < Character> ( ) ;
for ( char c : str. toCharArray ( ) ) {
lists. add ( c) ;
}
return lists. stream ( ) ;
}
f
l
a
t
m
a
p
(
)
是
扁
平
化
映
射
,
不
单
只
是
s
t
r
e
a
m
流
的
拼
接
,
还
有
S
t
r
i
n
g
数
组
或
L
i
s
t
集
合
也
是
可
以
进
行
扁
平
化
映
射
的
\color{#FF0000}{flatmap()是扁平化映射,不单只是stream流的拼接,还有String数组或List集合也是可以进行扁平化映射的}
f l a t m a p ( ) 是 扁 平 化 映 射 , 不 单 只 是 s t r e a m 流 的 拼 接 , 还 有 S t r i n g 数 组 或 L i s t 集 合 也 是 可 以 进 行 扁 平 化 映 射 的
排序
方法名 作用 sorted() 自然排序(Comparable) sorted(Comparator com) 定制排序(Comparator)
1. sorted
List< String> asList = Arrays. asList ( "wreew" , "dfa" , "sdfs" , "sdfs" ) ;
asList. stream ( ) . sorted ( ) . forEach ( System. out: : println) ;
2. sorted ( Comparator com)
emps. stream ( ) . sorted ( ( x, y) - > {
if ( x. getAge ( ) == y. getAge ( ) ) {
return x. getName ( ) . compareTo ( y. getName ( ) ) ;
} else {
return Integer. compare ( x. getAge ( ) , y. getAge ( ) ) ;
}
} ) . forEach ( System. out: : println) ;
3.Stream终止操作
查找与匹配
方法名 作用 allMatch 检查是否匹配所有的元素 anyMatch 检查是否至少匹配一个元素 noneMatch 检查是否没有匹配的所有元素 findFirst 返回第一个元素 findAny 返回当前流任意一个元素 (如果是并行流返回的是第一个 如果是串行流返回的是随机任意一个) count 返回流中元素的总个数 max 返回流中最大值 min 返回流中最小值
1. allMatch
boolean allMatch = emps. stream ( ) . allMatch ( ( emp) - > emp. getStatus ( ) . equals ( Status. BUSY) ) ;
System. out. println ( allMatch) ;
2. anyMatch
boolean anyMatch = emps. stream ( ) . anyMatch ( ( emp) - > emp. getStatus ( ) . equals ( Status. BUSY) ) ;
System. out. println ( anyMatch) ;
3. noneMatch
boolean noneMatch = emps. stream ( ) . noneMatch ( ( emp) - > emp. getStatus ( ) . equals ( Status. BUSY) ) ;
System. out. println ( noneMatch) ;
4.f indFirst
Optional< Emp> findFirst = emps. stream ( ) . findFirst ( ) ;
System. out. println ( findFirst. get ( ) ) ;
5.f indAny
Optional< Emp> findAny = emps. stream ( ) . filter ( ( emp) - > emp. getSalary ( ) > 2500 ) . findAny ( ) ;
System. out. println ( findAny. get ( ) ) ;
( parallelStream是并行流 多个线程同时找谁找到就算谁的)
Optional< Emp> findAny1 = emps. parallelStream ( ) . filter ( ( emp) - > emp. getSalary ( ) > 2500 ) . findAny ( ) ;
System. out. println ( findAny1. get ( ) ) ;
6. count
long count = emps. stream ( ) . count ( ) ;
System. out. println ( count) ;
7. max
Optional< Emp> max = emps. stream ( ) . max ( ( emp1, emp2) - > Double. compare ( emp1. getSalary ( ) , emp2. getSalary ( ) ) ) ;
System. out. println ( max. get ( ) ) ;
8. min
Optional< Double> min = emps. stream ( ) . map ( Emp: : getSalary) . min ( Double: : compareTo) ;
System. out. println ( min. get ( ) ) ;
归约
(BinaryOperator extends -> BiFunction extends -> Function)
方法名 作用 reduce(T identify, BinaryOperator) identify是起始值 reduce(BinaryOperator)
①注意: x=0; y=stream里面的元素 x = x + y;
List< Integer> lists = Arrays. asList ( 1 , 2 , 34 , 57 , 8 , 4 ) ;
Integer reduce = lists. stream ( ) . reduce ( 0 , ( x, y) - > x+ y) ;
System. out. println ( reduce) ;
收集
方法名 作用 collect 将流转化为其他形式。接受一个Collector接口的实现,用于给Stream中的元素做汇总的方法
Collectors类里有很多收集方法 和 收集方式
List< String> list = emps. stream ( ) . map ( Emp: : getName) . collect ( Collectors. toList ( ) ) ;
list. forEach ( System. out: : println) ;
Set< String> listset = emps. stream ( ) . map ( Emp: : getName) . collect ( Collectors. toSet ( ) ) ;
listset. forEach ( System. out: : println) ;
HashSet< String> collect = emps. stream ( ) . map ( Emp: : getName) . collect ( Collectors. toCollection ( HashSet: : new ) ) ;
collect. forEach ( System. out: : println) ;
String collect = emps. stream ( ) . map ( Emp: : getName) . collect ( Collectors. joining ( "," , "===" , "+++" ) ) ; 中间分隔符 首部 尾部
System. out. println ( collect) ;
总条数
Long collect = emps. stream ( ) . collect ( Collectors. counting ( ) ) ;
System. out. println ( collect) ;
平均值
Double collect2 = emps. stream ( ) . collect ( Collectors. averagingDouble ( Emp: : getSalary) ) ;
System. out. println ( collect2) ;
最大值
maxBy·············
最小值
minBy·············
分组
Map< Status, List< Emp> > collect = emps. stream ( ) . collect ( Collectors. groupingBy ( Emp: : getStatus) ) ;
System. out. println ( collect) ;
多级分组 分组下再次分组
Map< Status, Map< String, List< Emp> >> collect = emps. stream ( ) . collect ( Collectors. groupingBy ( Emp: : getStatus, Collectors. groupingBy ( ( emp) - > {
if ( emp. getAge ( ) < 18 ) {
return "青少年" ;
} else if ( emp. getAge ( ) > 18 && emp. getAge ( ) < 40 ) {
return "中年组" ;
} else {
return "老年组" ;
}
} ) ) ) ;
System. out. println ( collect) ;
分区 满足条件的分个区 不满足条件的分个区
Map< Boolean, List< Emp> > collect = emps. stream ( ) . collect ( Collectors. partitioningBy ( ( emp) - > emp. getSalary ( ) > 3000 ) ) ;
System. out. println ( collect) ;
获取总条数 总和 平均值 最大值 最小值 其它方式
DoubleSummaryStatistics collect = emps. stream ( ) . collect ( Collectors. summarizingDouble ( Emp: : getSalary) ) ;
System. out. println ( collect. getCount ( ) ) ;
System. out. println ( collect. getAverage ( ) ) ;
System. out. println ( collect. getSum ( ) ) ;
System. out. println ( collect. getMax ( ) ) ;
System. out. println ( collect. getMin ( ) ) ;
5.Optional 容器类的常用方法
方法名 作用 Optional.of(T t) 创建一个Optional实例 Optional.empty() 创建一个空的Optional实例 Optional.ofNullable(T t) 若t为不为null,创建Optional实例,t若为null,创建空实例 isPresent() 判断是否包含值 orElse(T t) 如果调用对象包含值,返回该值,否则返回t orElseGet(Supplier s) 如果调用对象包含值,返回该值,否则返回s获取的值 map(Function f) 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty() flatMap(Function mapper) 与map类似,要求返回值必须是Optional
5.1 Optional.of(T t) ①注意:如果 T 传的是null 会报空指针异常NullPointException
Optional< Emp> of = Optional. of ( new Emp ( ) ) ;
System. out. println ( of. get ( ) ) ;
5.2 Optional.empty() ①注意:空的Optional实例是get()方法获取不了的 会报java.util.NoSuchElementException: No value present
Optional< Emp> empty = Optional. empty ( ) ;
System. out. println ( empty. get ( ) ) ;
5.3 Optional.ofNullable(T t) 和 5.4 isPresent() 和 5.5 orElse(T t)
Optional< Emp> ofNullable = Optional. ofNullable ( null) ;
if ( ofNullable. isPresent ( ) ) {
System. out. println ( ofNullable. get ( ) ) ;
}
Emp emp = ofNullable. orElse ( new Emp ( ) ) ;
System. out. println ( emp) ;
5.6 orElseGet(Supplier s)
Optional< Emp> of = Optional. ofNullable ( null) ;
Emp orElseGet = of. orElseGet ( ( ) - > new Emp ( ) ) ;
System. out. println ( orElseGet) ;
5.7 map(Function f)
Optional< Emp> ofNullable = Optional. ofNullable ( new Emp ( "李志坚" , 14 , 88888888 , Status. FREE) ) ;
Optional< String> str = ofNullable. map ( Emp: : getName) ;
System. out. println ( str. get ( ) ) ;
6.default关键字
这个default和访问控制权的default不一样,这个default关键字只能修饰接口中的默认方法
权限 类内 同包 不同包子类 不同包非子类 private √ × × × default √ √ × × protected √ √ √ × public √ √ √ √
① 在java8新增了 ,在接口中可以有默认方法 用default修饰的方法 可以有方法体,然而default方法不会影响函数式接口。
② 并且接口中可以写静态方法和在类中的静态方法用法没区别
这样个default关键字优点
1 避免子类代码重复
当多个类实现一个接口的某个方法时,如果方法的具体实现代码相同,那么就会造成代码重复问题。接口增强相当于把公共的代码提取出来,放入接口定义中,实现类不需要重写该方法,解决了实现该接口的子类代码重复的问题。
2 克服单继承的缺陷
接口中可以定义static或default类型这两种有具体实现的方法,减少了接口和抽象类之间的区别。对于子类而言,抽象类只能单继承,接口可以实现多个。
7.新时间日期API
以前的时间日期API存在线程安全问题
类 作用 DateTimeFormatter 格式化时间/日期
静态方法:
实例方法:
LocalDate parse = LocalDate. parse ( "20181222" , DateTimeFormatter. BASIC_ISO_DATE) ;
System. out. println ( parse) ;
DateTimeFormatter ofPattern = DateTimeFormatter. ofPattern ( "yyyy年MM月dd日" ) ;
String format = ofPattern. format ( LocalDate. now ( ) ) ;
System. out. println ( format) ;
7.1. JAVA8中 给人读的时间有三个
类 作用 LocalDate 本地日期 LocalTime 本地时间 LocalDateTime 本地日期时间
上面的三个类都有这两个静态方法API
方法 作用 now() 获取当前日期/时间 of(…) 指定 数据 创建LocalDateTime对象
now()
LocalDate date = LocalDate. now ( ) ;
System. out. println ( date) ;
LocalTime time = LocalTime. now ( ) ;
System. out. println ( time) ;
LocalDateTime dateTime = LocalDateTime. now ( ) ;
System. out. println ( dateTime) ;
of(…)
LocalDate date = LocalDate. of ( 2020 , 5 , 9 ) ;
System. out. println ( date) ;
LocalTime time = LocalTime. of ( 22 , 48 , 22 ) ;
System. out. println ( time) ;
LocalDateTime dateTime = LocalDateTime. of ( date, time) ;
System. out. println ( dateTime) ;
上面的三个类都有这两个实例方法API
方法 作用 plus…() 给调用对象 加 minus…() 给调用对象 减 get…() 获取调用对象的 指定数据 with…() 指定数据到月或日
1. plus. . ( )
LocalDateTime now = LocalDateTime. now ( ) ;
LocalDateTime plusDays = now. plusDays ( 22 ) ;
System. out. println ( plusDays) ;
2. minus. . . ( )
LocalDateTime now = LocalDateTime. now ( ) ;
LocalDateTime plusDays = now. minusDays ( 22 ) ;
System. out. println ( plusDays) ;
3. get. . . ( )
LocalDateTime now = LocalDateTime. now ( ) ;
System. out. println ( now. getYear ( ) ) ;
4. with. . . ( )
LocalDate withDayOfMonth = LocalDate. now ( ) . withDayOfMonth ( 12 ) ;
System. out. println ( withDayOfMonth) ;
7.2. Instant 时间戳
类 作用 Instant 时间戳(以Unix 元年: 1970年1月1日00:00:00到某个时间之间的毫秒值)
静态方法:
1. now ( )
Instant now = Instant. now ( ) ;
System. out. println ( now) ;
实例方法:
方法 作用 atOffset(ZoneOffset.of…()) 设置时区时差 toEpochMilli() 转化成毫秒 getEpochSecond() 转化成秒 getNano() 转化成纳秒
1. atOffset ( ZoneOffset. of. . . ( ) )
OffsetDateTime atOffset = now. atOffset ( ZoneOffset. ofHours ( 8 ) ) ;
System. out. println ( atOffset) ;
1. toEpochMilli ( )
2. getEpochSecond ( )
3. getNano ( )
System. out. println ( now. toEpochMilli ( ) ) ;
System. out. println ( now. getEpochSecond ( ) ) ;
System. out. println ( now. getNano ( ) ) ;
7.3. Duration Period
类 作用 Duration 计算两个’时间‘之间的间隔 Period 计算两个‘日期’之间的间隔
1.D uration between 计算两个时间之间的间隔 toMillis ( ) 转换成毫秒
Instant begin = Instant. now ( ) ;
Instant end = Instant. now ( ) ;
Duration between = Duration. between ( begin, end) ;
System. out. println ( between. toMillis ( ) ) ;
2. Period between 计算两个日期之间的间隔 getMonths ( ) getDays ( ) 间隔的月和日
LocalDate ld1 = LocalDate. of ( 2015 , 12 , 13 ) ;
LocalDate ld2 = LocalDate. now ( ) ;
Period between = Period. between ( ld1, ld2) ;
System. out. println ( between. getMonths ( ) ) ;