Java8新特性
1. lambda表达式
1.1lambda表达式入门案例
先来看如下代码,输出的都是同样的结果,但是代码越来越简洁
package com.xiaowang;
import org.junit.Test;
import java.util.Comparator;
/**
* @Author:小王吖
* @Date:2022/10/10
*/
public class lambda1 {
@Test
public void Test(){
System.out.println("======普通写法=======");
//就是通过new一个接口的匿名内部类去完成compare方法的重写
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
System.out.println("普通写法:"+comparator.compare(1,2));
System.out.println("======lambda写法=======");
Comparator<Integer> comparator1= (o1, o2)->Integer.compare(o1,o2);
System.out.println("lambda引用:"+comparator1.compare(1,2));
System.out.println("======方法引用写法=======");
Comparator<Integer> comparator2=Integer::compare;
System.out.println("方法引用:"+comparator2.compare(1,2));
}
}
输出:
1.2 lambda表达式介绍
1. lambda表达式格式:
- -> :lambda操作符 或 箭头操作符
- ->左边:lambda表达式形参列表 (也就是接口中的抽象方法的形参列表)
- ->右边:lambda体 (也就是重写的抽象方法的方法体)
2. lambda表达式的重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
3. 使用 Lambda 表达式需要注意以下两点:
- Lambda 表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。
- Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。
4. lambda表达式总结:
- ->左边:lambda表达式形参列表的参数类型阔以省略,如果只有一个参数,小括号也可以省略
- ->右边:lambda体 只有一条执行语句 可以省略大括号及return关键字(随着大括号一起),不止一条执行语句就可以不省
1.3 lambda表达式六种语法
package com.xiaowang;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
* @Author:小王吖
* @Date:2022/10/10
*/
/*
* 1.举例:(o1,o2) -> Integer.compare(o1,o2)
* 2.格式:
* -> :lambda操作符 或 箭头操作符
* ->左边:lambda表达式形参列表 (也就是接口中的抽象方法的形参列表)
* ->右边:lambda体 (也就是重写的抽象方法的方法体)
* 3.lambda表达式的使用 (6种情况)
* 总结:
* ->左边:lambda表达式形参列表的参数类型阔以省略,如果只有一个参数,小括号也可以省略
* ->右边:lambda体 只有一条执行语句 可以省略大括号及return关键字(随着大括号一起),不止一条执行语句就可以不省
* 4.lambda表达式的本质:作为接口的实例
* */
public class lambda2 {
//语法一:无参,无返回值
@Test
public void Test(){
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("java64");
}
};
runnable1.run();
Runnable runnable2 = () -> System.out.println("java64");
runnable2.run();
}
@Test
public void Test1(){
//语法二:lambda 需要一个参数,但是没有返回值
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("Java64啊~");
Consumer<String> con1 = (String s) ->System.out.println(s);
con1.accept("java64啊~~");
}
//语法三:数据类型阔以省略,因为可由编译器推断出,称为“类型推断”
@Test
public void Test2(){
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("Java64啊~");
Consumer<String> con1 = (s) ->System.out.println(s);
con1.accept("java64啊~~");
}
//语法格式四:lambda 若只需要一个参数的时候,参数的小括号阔以省略
@Test
public void Test3(){
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("Java64啊~");
Consumer<String> con1 = s ->System.out.println(s);
con1.accept("java64啊~~");
}
//语法格式五:lambda 若需要两个或以上的参数,多条执行语句,并且阔以有返回值
@Test
public void Test4(){
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2) ;
}
};
comparator.compare(1,2);
Comparator<Integer> comparator1 =(o1,o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2) ;
};
comparator1.compare(1,2);
}
//语法格式六:lambda 体只有一条语句的时候,如果有return和大括号,都可以省略
@Test
public void Test5(){
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2) ;
}
};
System.out.println(comparator.compare(1,2));
Comparator<Integer> comparator1 =(o1,o2) -> o1.compareTo(o2) ;
System.out.println(comparator.compare(1,2));
}
}
2. 方法引用
2.1 方法引用案例讲解
1. 方法引用三种类型:
- 对象::非静态方法(实例方法)
- 类::静态方法
- 类::非静态方法
2. 本质
是lambda表达式,也是一个函数式接口,相当于替换了lambda表达式的方法体
3. 使用场景:
- 当要传递给Lambda表达式体的操作,已经有实现的方法了,就可以使用方法使引用
- 一个接口的抽象方法的实现体的功能与一个类所含有的某一个方法的功能类似,,类方法更简洁
- 并且参数列表和返回类型一样,这时就可以用这个类去调用方法,就会更加的简洁
4. 方法使用要求:
接口中的抽象方法,形参列表和返回值类型要和方法引用的形参列表和返回值类型相同(情况三不满足,少用)
package com.xiaowang.method;
import org.junit.Test;
import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* @Author:小王吖
* @Date:2022/10/10
*/
/*
* 方法引用:
*1.使用情景:当要传递给Lambda表达式体的操作,已经有实现的方法了,就可以使用方法使引用
* 一个接口的抽象方法的实现体的功能与一个类所含有的某一个方法的功能类似,,类方法更简洁
* 并且参数列表和返回类型一样,这时就可以用这个类去调用方法,就会更加的简洁
*
* 2.本质:是lambda表达式,也是一个函数式接口,相当于替换了lambda表达式的方法体
*
* 3.格式:类(对象)::方法名
*
* 4.三种格式:
* 对象::非静态方法(实例方法)
* 类::静态方法
* 类::非静态方法
*
*5.方法使用要求:接口中的抽象方法,形参列表和返回值类型要和方法引用的形参列表和返回值类型相同(情况三不满足,少用)
* */
public class MethodRefTest {
//情况一:对象::实例方法(非静态方法)
//lambda表达式:Consumer中的void accept(T t) 相当于PrintStream类的一个方法可以替换Consumer接口的抽象方法
//方法引用:PrintStream中的void println(T t)
@Test
public void Test1() {
//lambda表达式
Consumer<String> consumer = s -> System.out.println(s);
consumer.accept("lambda写法");
System.out.println("================");
//方法引用
PrintStream out = System.out;//获取流对象
Consumer<String> consumer1 = out::println;//使用对象来调用其方法
consumer1.accept("方法引用");//
}
//lambda表达式:Supplier中的 T get()
//方法引用:Emolyee中的String getName()
@Test
public void Test2() {
Emolyee emolyee = new Emolyee(1, "小王", 21, 5222);
//lambda表达式
Supplier<String> supplier = () -> emolyee.getName();
System.out.println(supplier.get());
;//调用lambda表达式的方法体
System.out.println("================");
//方法引用
Supplier<String> supplier1 = emolyee::getName;
System.out.println(supplier1.get());
}
//情况二: 类::静态方法
//Comparator 中的 int compare(T t1,T t2)
//Integer 中的int compare(T t1,T t2)
@Test
public void Test3() {
Comparator<Integer> comparator = (t1, t2) -> Integer.compare(t1, t2);
System.out.println(comparator.compare(1, 2));
Comparator<Integer> comparator1 = Integer::compare;
System.out.println(comparator1.compare(1, 2));
}
//Function中的R apply(T t)
//Math中的Long round(Double d)
@Test
public void Test4() {
Function<Double, Long> function = d -> Math.round(d);
System.out.println(function.apply(120.2));
//System.out.println(function.equals(12.5));
Function<Double, Long> function1 = Math::round;
System.out.println(function1.apply(120.2));
// System.out.println(function1.equals(12.5));
}
//情况三:类::实例方法(非静态方法)!!
//Comparator中的int compare(T t1,T t2) 第一个参数作为方法引用里面的调用者,第二个为参数
//String 中的int t1.compareTo(t2)
@Test
public void Test5() {
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
System.out.println(comparator.compare("1", "2"));
Comparator<String> comparator1 = (s1, s2) -> s1.compareTo(s2);
System.out.println(comparator1.compare("1", "2"));
Comparator<String> comparator2 = String::compareTo;
System.out.println(comparator2.compare("1", "2"));
}
//BiPredicate中的boolean test(T t1,T t2)
//String中的boolean t1.equals(t2)
@Test
public void Test6() {
BiPredicate<String, String> biPredicate = new BiPredicate<String, String>() {
@Override
public boolean test(String s, String s2) {
return s.equals(s2);
}
};
System.out.println(biPredicate.test("1", "2"));
BiPredicate<String, String> biPredicate1 = (t1, t2) -> t1.equals(t2);
System.out.println(biPredicate1.test("1", "2"));
BiPredicate<String, String> biPredicate2 = String::equals;
System.out.println(biPredicate2.test("1", "2"));
}
//
@Test
public void Test7() {
Emolyee emolyee = new Emolyee(1, "小王", 21, 5222);
Function<Emolyee,String > function = new Function<Emolyee, String>() {
@Override
public String apply(Emolyee emolyee) {
return emolyee.getName();
}
};
System.out.println(function.apply(emolyee));
Function<Emolyee,String > function1 =e -> e.getName();
System.out.println(function1.apply(emolyee));
Function<Emolyee,String > function2 =Emolyee::getName;
System.out.println(function2.apply(emolyee));
}
}