Java 8新特性
1.Lambda表达式
Lambda是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
1.1 格式:
- -> : lambda操作符或箭头操作符
- ->的左边:lambda形参列表(接口中的抽象方法的形参列表)
- ->的右边:lambda体(重写抽象方法的方法体)
1.2 Lambda表达式的本质
在Java中本质就是作为接口的具体实现类的对象
要求:函数式接口
1.3 Lambda表达式的使用(6种情况举例)
- lambda形参列表的参数类型可以省略,如果只有一个参数,括号也可省
- lambda体,如果只有一个语句可省略大括号
1.3.1 无参,无返回值
public void test1(){
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello World!");
}
};
r1.run();
System.out.println("----Lambda表达式----");
Runnable r2 = () -> System.out.println("Hello World!");
r2.run();
}
1.3.2 需要一个参数,但是没有返回值
public void test2(){
Consumer<String> con = new Consumer<String>(){
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("Hello");
System.out.println("----Lambda表达式----");
Consumer<String> con1 = (String s) -> System.out.println(s);
con1.accept("Lambda");
}
1.3.3 数据类型可以省略,因为可由编译器推断得出,称为 类型推断
public void test3(){
Consumer<String> con1 = (String s) -> System.out.println(s);
con1.accept("Lambda");
System.out.println("----Lambda表达式----");
Consumer<String> con2 = (s) -> System.out.println(s);
con2.accept("Lambda");
}
1.3.4 Lambda若只需要一个参数时,参数的小括号可以省略
public void test4(){
Consumer<String> con2 = (s) -> System.out.println(s);
con2.accept("Lambda");
System.out.println("----Lambda表达式----");
Consumer<String> con3 = s -> System.out.println(s);
con3.accept("Lambda");
}
1.3.5 Lambda 需要两个或两个以上的参数,多条语句执行,并且有返回值
public void test5(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1,Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(12, 14));
System.out.println("----Lambda表达式----");
Comparator<Integer> com2 = (o1,o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(com2.compare(13, 11));
}
1.3.6 当Lambda体只有一条语句时,return与大括号若有,都可省略
public void test6(){
Comparator<Integer> com2 = (o1,o2) -> {
return o1.compareTo(o2);
};
System.out.println(com2.compare(13, 11));
System.out.println("----Lambda表达式----");
Comparator<Integer> com3 = (o1,o2) -> o1.compareTo(o2);
System.out.println(com3.compare(10, 11));
}
2.函数式Function()接口
- 如果一个接口中,只声明了一个抽象方法,则称该接口为函数式接口。
- 检验是否是函数式接口==@FunctionalInterface==
- 在java.util.function包下定义了Java8的丰富的函数式接口
//检验是否是函数式接口
@FunctionalInterface
public interface MyInterface {
void method1();
}
2.1 Java内置四大核心函数式接口
2.2 其他函数式接口
3.方法引用与构造器引用
3.1 方法引用
当要传递给Lambda体的操作,已经有实现的方法,就可以使用方法引用!
- 方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
- 要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!
- 格式:使用操作符“::”将类(或对象)与方法名分隔开来。
- 如下三种主要使用情况:
- 对象 :: 实例方法名
- 类 :: 静态方法名
- 类 :: 实例方法名
public class MethodRefTest {
//情况一:对象的引用::实例方法名
@Test
public void test(){
Consumer<String> consumer1 = str -> System.out.println(str);
consumer1.accept("Hello");
System.out.println("-------方法引用--------");
PrintStream ps = new PrintStream(System.out);
Consumer<String> consumer2 = ps :: println;
consumer2.accept("World");
}
@Test
public void test2() {
Person person = new Person();
Supplier<String> sup = () -> person.getName();
String str = sup.get();
System.out.println(str);
System.out.println("-------方法引用--------");
// 对象的引用 :: 实例方法名
Supplier<Integer> sup2 = person::getAge;
Integer num = sup2.get();
System.out.println(num);
}
//情况二: 2. 类名 :: 静态方法名
@Test
public void test3() {
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
int compare = com.compare(2, 3);
System.out.println(compare);
System.out.println("-------方法引用--------");
// 类名 :: 静态方法名
Comparator<Integer> com2 = Integer::compare;
System.out.println(com2.compare(12, 10));
}
//情况三: 类名 :: 实例方法名
@Test
public void test4() {
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
// 使用要求: 若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式:
// ClassName::MethodName
BiPredicate<String, String> bp2 = String::equals;
boolean test = bp2.test("hello", "hello");
System.out.println(test);
}
}
3.2 构造器引用
格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!
//二、构造器引用 :构造器的参数列表,需要与函数式接口中参数列表保持一致!
//1. 类名 :: new
//ClassName::new
//注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致、
@Test
public void test5() {
Supplier<Person> sup =()->new Person();
//构造器引用方式
Supplier<Person> sup2=Person::new;
Person person = sup2.get();
System.out.println(person);
}
@Test
public void test6() {
Function<Integer,Person> fun=(x)->new Person(x);
Function<Integer,Person> fun2=Person::new;
Person person = fun2.apply(101);
System.out.println(person);
//需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致、
//这里的参数列表,就对应person的构造器的列表一样
BiFunction<Integer,Integer,Person> bif=Person::new;
Person apply = bif.apply(2, 3);
System.out.println(apply);
}
3.3 数组引用
格式:type[]::new
//三、数组引用
//类型[] :: new;
@Test
public void test7() {
Function<Integer,String[]> fun=(x)->new String[x];
String[] apply = fun.apply(10);
System.out.println(apply.length);
Function<Integer,String[]> fun2=String[]::new;
String[] apply2 = fun2.apply(10);
System.out.println(apply2.length);
}
4.Stream API
Java8 Stream:2万字20个实例,玩转集合的筛选、归约、分组、聚合_云深不知处-CSDN博客_java stream 聚合