Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口
演示代码下载地址:https://github.com/prettyRain/java8demo.git
1.引入lambda表达式
1)用接口Runnable演示
@Test
public void test6(){
//以前的匿名内部类
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("lambda");
}
};
runnable.run();
//现在的lambda表达式
Runnable runnable1 = () -> System.out.println("lambda");
runnable1.run();
}
2)自己写接口演示普通调用、匿名内部类调用、lambda表达式调用
Student类 用于演示的学生对象
package com.ge.lambda;
import java.math.BigDecimal;
/**
* 学生类
*/
public class Student {
public static String getStr(Integer grade){
if(Integer.compare(grade,60) > 0){
return "三好学生";
}
return "不及格";
}
private Long id;//id
private String name;//学生姓名
private String sex;//性别
private Integer age;//年龄
private BigDecimal price;//工资
public Student() {
}
public Student(Long id, String name, String sex, Integer age, BigDecimal price) {
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
this.price = price;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (!id.equals(student.id)) return false;
if (!name.equals(student.name)) return false;
if (!sex.equals(student.sex)) return false;
if (!age.equals(student.age)) return false;
return price.equals(student.price);
}
@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + name.hashCode();
result = 31 * result + sex.hashCode();
result = 31 * result + age.hashCode();
result = 31 * result + price.hashCode();
return result;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", price=" + price +
'}';
}
}
接口 FilterStudent
package com.ge.lambda;
/**
* 接口
*/
public interface FilterStudent {
public boolean test(T t);
}
FilterStudentForAgeImpl 判断年龄接口实现类
package com.ge.lambda;
/**
* 判断年龄的实现类
*/
public class FilterStudentForAgeImpl implements FilterStudent {
@Override
public boolean test(Student student) {
if(student.getAge() > 12){
return true;
}else{
return false;
}
}
}
FilterStudentForPriceImpl 判断学生工资的实现类
package com.ge.lambda;
import java.math.BigDecimal;
/**
* 判断学生工资的实现类
*/
public class FilterStudentForPriceImpl implements FilterStudent {
@Override
public boolean test(Student student) {
if(student.getPrice().compareTo(new BigDecimal(5000)) >= 0){
return true;
}
return false;
}
}
普通调用、匿名内部类调用、lambda表达式调用
Student[] aa = new Student[]{new Student(1L,"小明","男",18,new BigDecimal(5000)),
new Student(2L,"小花","女",12,new BigDecimal(6000)),
new Student(3L,"小李","男",10,new BigDecimal(3000)),
new Student(4L,"小刘","男",17,new BigDecimal(9000)),
new Student(5L,"小刚","男",13,new BigDecimal(8000))};
//策略设计模式
public List filterStudent(List students,FilterStudent filterStudent){
List studentList = new ArrayList();
for(Student student:students){
if(filterStudent.test(student)){
studentList.add(student);
}
}
return studentList;
}
/**
* 普通调用实现类
*/
@Test
public void test3(){
List listForAge = filterStudent(stus,new FilterStudentForAgeImpl());
for(Student student:listForAge){
System.out.println(student.toString());
}
System.out.println("-----------------------------");
List listForPrice = filterStudent(stus,new FilterStudentForPriceImpl());
for(Student student:listForPrice){
System.out.println(student.toString());
}
}
/**
* 通过匿名类实现
*/
@Test
public void test4(){
List list = filterStudent(stus,new FilterStudent(){
@Override
public boolean test(Student student) {
if(student.getAge() > 13){
return true;
}
return false;
}
});
for(Student student:list){
System.out.println(student.toString());
}
}
/**
* lambda表达式调用
*/
@Test
public void test5(){
List list = filterStudent(stus,(e) -> e.getAge() >= 12 );
for(Student student:list){
System.out.println(student.toString());
}
System.out.println("-------------------------");
List list1 = filterStudent(stus,(e) -> e.getPrice().compareTo(new BigDecimal(8000)) >= 0 );
for(Student student:list1){
System.out.println(student.toString());
}
}
2.lambda表达式六种语法格式:
- 1)lambda表达式的基本语法
- 箭头操作符将lambda表达式拆分成两部分;
左侧:lambda表达式的参数列表
右侧:lambda表达式中所需要执行的功能,即lambda体
- 箭头操作符将lambda表达式拆分成两部分;
- 2)语法格式:
- 语法格式一:无参数,无返回值
() -> System.out.println("Hello Lambda!"); - 语法格式二:有一个参数,并且无返回值
(x) -> System.out.println(x) - 语法格式三:若只有一个参数,小括号可以省略不写
x -> System.out.println(x) - 语法格式四:有两个以上参数,有返回值,并且lambda体中有多条语句
Comparatorcom = (x, y) -> {
System.out.println("函数式接口");
return Integer.compare(x, y);
}; - 语法格式五:若 Lambda 体中只有一条语句,有返回值, return 和 大括号都可以省略不写
Comparatorcom = (x, y) -> Integer.compare(x, y); - 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
(Integer x, Integer y) -> Integer.compare(x, y);
- 语法格式一:无参数,无返回值
package com.ge.lambda;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/*
* 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符
* 箭头操作符将 Lambda 表达式拆分成两部分:
* 左侧:Lambda 表达式的参数列表
* 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
* 语法格式一:无参数,无返回值
* () -> System.out.println("Hello Lambda!");
* 语法格式二:有一个参数,并且无返回值
* (x) -> System.out.println(x)
* 语法格式三:若只有一个参数,小括号可以省略不写
* x -> System.out.println(x)
* 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
* Comparator com = (x, y) -> {
* System.out.println("函数式接口");
* return Integer.compare(x, y);
* };
*
* 语法格式五:若 Lambda 体中只有一条语句,有返回值, return 和 大括号都可以省略不写
* Comparator com = (x, y) -> Integer.compare(x, y);
*
* 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
* (Integer x, Integer y) -> Integer.compare(x, y);
*
*
* 二、Lambda 表达式需要“函数式接口”的支持
* 函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。 可以使用注解 @FunctionalInterface 修饰
* 可以检查是否是函数式接口
*/
public class TestLambda2 {
/**
* 无参 无返回值
*/
@Test
public void test1(){
Runnable r = () -> System.out.println("lambda");
r.run();
}
/**
* 有一个参数,并且无返回值
*/
@Test
public void test2(){
Consumer con = (x) -> System.out.println(x);
con.accept("有一个参数,并且无返回值");
}
/**
* 若只有一个参数,小括号可以省略不写
*/
@Test
public void test3(){
Consumer con = x -> System.out.println(x);
con.accept("若只有一个参数,小括号可以省略不写");
}
/**
* 有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
*/
@Test
public void test4(){
Comparator comparator = (x,y) -> {
System.out.println("函数式接口");
return Integer.compare(x,y);
};
System.out.println(comparator.compare(5,6));
}
/**
* 若 Lambda 体中只有一条语句,有返回值, return 和 大括号都可以省略不写
*/
@Test
public void test5(){
Comparator comparator = (x,y) -> Integer.compare(x,y);
System.out.println(comparator.compare(5,6));
}
/**
* Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
*/
@Test
public void test6(){
Comparator comparator = (Integer x,Integer y) -> Integer.compare(x,y);
System.out.println(comparator.compare(5,6));
}
}
3.java8内置的四大核心函数式接口
- 1)Consumer
: 消费型接口
方法: void accept(T t) - 2)Supplier
: 供给型接口
方法: T get(); - 3)Function
: 函数型接口
方法: R apply(T t); - 4)Predicate
: 断言型接口
方法: boolean test(T t);
package com.ge.lambda;
import org.junit.Test;
import javax.print.DocFlavor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/*
* Java8 内置的四大核心函数式接口
*
* Consumer : 消费型接口
* void accept(T t);
*
* Supplier : 供给型接口
* T get();
*
* Function : 函数型接口
* R apply(T t);
*
* Predicate : 断言型接口
* boolean test(T t);
*
*/
public class TestLambda3 {
/**
* Consumer消费型接口
*/
@Test
public void test1(){
Consumer consumer = x -> System.out.println(x);
consumer.accept("consumer消费型接口");
}
/**
* Supplier供给型接口
*/
@Test
public void test2(){
Supplier supplier= () -> (int)(Math.random()*100);
System.out.println(supplier.get());
}
/**
* Function(T,R)函数型接口
*/
@Test
public void test3(){
String resultstr = strHander("jjfsdjsjdsjiojwijf",(x) -> x.substring(2,5));
System.out.println(resultstr);
}
public String strHander(String str, Function fun){
return fun.apply(str);
}
/**
* 断言型接口
*/
@Test
public void test4(){
List list = Arrays.asList("aaa","bbb","cccc","dddd");
List returnlist = getList(list,(x) -> x.length() > 3);
System.out.println(Arrays.toString(returnlist.toArray()));
}
public List getList(List list, Predicate predicate){
ArrayList returnlist = new ArrayList();
for(String str:list){
if(predicate.test(str)){
returnlist.add(str);
}
}
return returnlist;
}
}
4.方法引用、构造器引用、数组引用
- 1)方法引用:若lambda体中的功能,已经有方法提供了实现,可以使用方法引用(可以理解为lambda表达式的另一种表现形式)
- 1.对象的引用::实例方法名
- 2.类名::静态方法名
- 3.类名::实例方法名
- 注意:①方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
②若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
- 2)构造器引用:构造器的参数列表,需要与函数式接口中参数列表保持一致
- 1.类名::new
- 3)数组引用
- 1.类型[]::new
/**
* 对象的引用 :: 实例方法名
*/
@Test
public void test1(){
//消费型
Consumer consumer = (x) -> System.out.println(x);
Consumer consumer1 = System.out::println;
consumer.accept("consumer:以前的写法");
consumer.accept("consumer1:现在的写法");
//供给型
Student student = new Student(1l,"小明","男",12,new BigDecimal(2000));
Supplier supplier = student::getName;
System.out.println(supplier.get());
}
/**
* 类名 :: 静态方法名
*/
@Test
public void test2(){
//函数型接口
Function fun = Student::getStr;
System.out.println(fun.apply(100));
}
/**
* 类名 :: 实例方法名 把类名当一个参数来处理
*/
@Test
public void test3(){
//断言型接口
BiPredicate biPredicate = (x,y) -> x.equals(y);
System.out.println(biPredicate.test("222","333"));
BiPredicate biPredicate1 = String::equals;
System.out.println(biPredicate1.test("222","333"));
Function fun = (e) -> e.toString();
System.out.println(fun.apply(new Student(1l,"小明","男",12,new BigDecimal(2000))));
Function fun1 = Student::toString;
System.out.println(fun.apply(new Student(1l,"小明","男",12,new BigDecimal(2000))));
}
/**
* 构造器引用
*/
@Test
public void test4(){
Supplier supplier = () -> new Student(1l,"小明","男",12,new BigDecimal(2000));
System.out.println(supplier.get().toString());
Supplier studentSupplier = Student::new;
System.out.println(studentSupplier.get().toString());
}
/**
* 数组引用
*/
@Test
public void test5(){
//函数型接口
Function function = (x) -> new String[x];
System.out.println(function.apply(3).length);
Function function1 = String[]::new;
System.out.println(function1.apply(3).length);
}