1、Lambda表达式
2、函数式接口
3、方法引用与构造器引用
4、Stream API
5、接口中的默认方法与静态方法
6、新时间日期API
1、Lambda表达式的基础语法,Java8中引入了一个新的操作符" -> ",称为箭头操作符或者Lambda操作符
Lambda表达式的基础语法,Java8中引入了一个新的操作符" -> ",称为箭头操作符或者Lambda操作符,箭头操作符将Lambda表达式拆分为2部分
左侧:Lambda 表达式的参数列表
右侧:Lambda 表达式中所执行的功能,即Lambda体
Lambda需要函数式接口的支持
接口中只有一个抽象方法的接口就是函数式接口,可以用 @FunctionalInterface注解检查是否是函数式接口
Lambda语法格式1:
无参数、无返回值 () -> System.out.println("Hello world");
public void t1(){
#以前写法(匿名内部类)
Runnable r = new Runnable(){
public void run(){
System.out.println("Hello world");
}
}
#现在写法
Runnabel r1 = () -> System.out.println("Hello Lambda");
}
Lambda语法格式2( ()括号可写可不写 ):
有一个参数,无返回值 (x) -> System.out.println("Hello Lambda");
有一个参数,无返回值 x -> System.out.println("Hello Lambda");
Lambda语法格式3():
有多个参数,多条语句,有返回值
(x, y, z) -> {
System.out.println("Hello Lambda");
System.out.println("Hello Lambda");
return x+y;
}
Lambda语法格式4():
Lambda体中只有一条语句,有返回值,大括号和return 都可以不写
(x, y, z) -> x+y+z
Lambda语法格式5():
Lambda表达式的参数类型可以不写,JVM编译器可以根据上下文进行类型推断
(x, y, z) -> x+y+z
Java8内置的四大核心函数式接口
Consumer<T>: 消费型接口 void accept(T t)
Supplier<T>: 供给型接口 T get()
Function<T, R>: 函数型接口 R apply(T t)
Predicate<T>: 断言型接口 boolean test(T t)
#使用内置的函数式接口
public void test2(Long a, Consumer<Long> con){
con.accept(a)
}
public void test1(){
test2(100, (t)->System.out.println("xxxx"+a));
}
方法引用:若Lambda体中的内容有方法已经实现了,我们可以使用方法引用,实现的方法的参数必须与Lambda表达式的参数一致
主要有3中语法格式
1、对象::实例方法名
2、类::静态方法名
3、类::实例方法名
//对象::实例方法名
public void test1(){
Consumer<String> con = (x)-> System.out.println(x); #简写前
Consumer<String> con1 = System.out::println; #简写后
Account account = new Account();
account.setAddress("xxxxxxxxxxx");
account.setAge(100);
Supplier<String> su1 = () -> account.getAddress(); #简写前
Supplier<String> su2 = account::getAddress; #简写后
Supplier<Integer> su3 = account::getAge; #简写后
System.out.println(su1.get());
System.out.println(su2.get());
System.out.println(su3.get());
}
//类::静态方法名,Lambda体中的方法参数、返回值必须与函数式接口的参数、返回值保持一致
Comparator<Integer> com1 = (x1, x2) -> Integer.compare(x1, x2); //简写前
Comparator<Integer> com2 = Integer::compare; //简写后
//类::实例方法名,Lambda体中的方法参数、返回值必须与函数式接口的参数、返回值保持一致,并且是第一个参数调用第二个参数
//若Lambda参数列表中的第一参数是实例方法的调用者,第二个参数是实例方法的参数时,可以使用ClassName::method
BiPredicate<String, String> bip1 = (x, y) -> x.equals(y); //简写前
BiPredicate<String, String> bip2 = String::equals; //简写后
流(Stream)到底是什么
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列,集合讲的是数据,流讲的是计算
1、Stream 自己不会存储元素
2、Stream 不会改变源对象,相反,他们会返回一个持有结果的新Stream
3、Stream 操作是延迟执行的,因为他们会等到需要结果的时候才执行
//生成Stream(流)的几种方式
List<String> list1 = new ArrayList<>();
Stream<String> stream1 = list1.stream();
String[] a1 = {"a1", "s2"};
Stream<String> stream2 = Arrays.stream(a1);
Stream<String> stream3 = Stream.of("a1", "a2", "a3");
//生成无限流
Stream<Integer> stream4 = Stream.iterate(0, x->x+2);
//stream4.limit(10).forEach(System.out::println);
//生成无限流
Stream.generate( ()-> Math.random() ).limit(5).forEach(System.out::println);
//中间操作
List<Account> accounts = new ArrayList<>();
accounts.add(.....);
accounts.stream().limit(2)
.filter((e)->{e.getAge()>30})
.skip(2)
.distinct()
.forEach(System.out.println);
//limit 截断流,使其不超过指定数量
//skip 返回一个扔掉前N个元素的流
//distinct 根据hashcode和equals去重
//filter 从流中排除某些元素
//forEach 是终止操作
//map(映射),接收Lambda,将元素转换为其他形式或提取信息,接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
// flatMap 接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有的流连接成一个流