语法格式:
()-> 结果表达式
参数-> 结果表达式
(参数1,参数2...,参数n)-> 结果表达式
第1行实现无参方法,单独写一对圆括号表示方法无参数,操作符右侧的结果表达式表示方法的返回值。
第2行实现只有一个参数的方法,参数可以写在圆括号里,或者不写圆括号。
第3行实现多参数的方法,所有参数按顺序写在圆括号里,且圆括号不可以省略。
lambda表达式也可以实现复杂方法,将操作符右侧的结果表达式换成代码块即可
语法格式如下:
()->{代码块)
参数->(代码块}
(参数1,参数2,..参数n)->{代码块)
lambda表达式的功能归纳总结,语法理解为:
() -> {代码块}
这个方法 按照 这样的代码来实现
开发者可以常见自定义的函数式接口
例如:
interface MyInterface{
void method();
}
如果接口中包含一个以上的抽象方法,则不符合函数式接口的规范,这样的接口不能用Iambda表达式创建匿名对象
interface SayHiInterface{ //例题14.1
String say();//抽象方法接口
}
public class NoParamterDemo {
public static void main(String[] args) {//利用匿名内部类补全方法体
//lambda表达式实现发招呼接口,返回抽象方法结果
SayHiInterface pi=()->"你好啊,这是lanbda表达式";
System.out.print(pi.say());
}
}
如果抽象方法中只有一个参数,lambda表达式则可以省略圆括号
例题14.2
interface AddInt{
int add(int a,int b);
}
public class ParamDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*无参数 AddInt ai1 = new AddInt() {
public int add(int a,int b) {
return a+b;
}
};
System.out.println("匿名内部类:" + ai1.add(3,5));
//使用Lambda表示式补全方法体
AddInt ai2 = (a, b) ->{
return a+b;
};
System.out.println("lambda表达式:" + ai2.add(3,5));
}
}*/
AddInt np=(x,y)->x+y; //表达式
int result=np.add(15,26); //调用接口方法
System.out.println("相加结果:"+result); //输出相加结果
}
}
ambda表达式中的参数不需要与抽象方法的参数名称相同,但顺序必须相同
lambda表达式会自动判断返回值类型是否符合抽象方法的定义
例题14.3
interface CheckGrade{ //例题14.3
String check(int grade); //查询成绩结果
}
public class GradeDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
CheckGrade g =(n)-> { //lambda表达式实现代码块
if (n>=90&& n<=100) { //如果成绩在90~100
return"成绩为优"; //输出成绩为优
}else if (n>=80&& n<=90) { //如果成绩在80~90
return"成绩为良"; //输出成绩为良
}else if (n>=60&& n<=80) { //如果成绩在60~80
return"成绩为中"; //输出成绩为中
}else if (n>=0&& n<=60) { //如果成绩在00~60
return"成绩为差"; //输出成绩为差
}else { //其他数字不是有效成绩
return"成绩无效"; //输出成绩无效
}
};
System.out.println(g.check(89));
}
}
这些外部的变量有些可以被更改,有些则不能。例如,lambda表达式无法更改局部变量的值,但是却可以更改外部类的成员变量(也可以叫做类属性)的值他。
局部变量在lambda表达式中默认被定义为final(静态)的,也就是说,lambda表达式只能调用局部变量,却不能改变其值。
例题14.4
interface VariableInterface1{ //例题14.4
void method();
}
public class VariableDemo1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int value=100;
VariableInterface1 v=()->{
int num=value-90;
value=12;
};
}
}
类成员变量是在lambda表达式中不是被final修饰的,所以lambda表达式可以改变其值
例题14.5
interface VariableInterface2{ //测试接口
void method(); //测试方法
}
public class VariableDemo2 { //测试类
int value = 100; //创建类成员变量
public void action() { //创建类成员方法
VariableInterface2 v=()->{ //实现测试接口
value =-12; //更改成员变量,没提示任何错误
};
System.out.println("运行接口方法前value="+value); //运行接口方法前先输出成员变量值
v.method(); //运行接口方法
System.out.println("运行接口方法后value="+value); //运行接口方法后再输出成员变量值
}
public static void main(String[] args) {
VariableDemo2 demo = new VariableDemo2(); //创建测试类对象
demo.action(); //执行测试类方法
}
}
lambda 表达式可以调用并修改类成员变量的值
lambda表达式只是描述了抽象方法是如何实现的,在抽象方法没有被调用前,lambda表达式中的代码并没有被执行,所以运行抽象方法之前类成员变量的值不会发生变化。
只要抽象方法被调用,就会执行lambda 表达式中的代码,类成员变量的值就会被修改。
lambda 表达式中并有抛出异常的语法,这是因为lambda表达式会默认抛出抽象方法原有的异常,当此方法被调用时则要进行异常处理。
例题14.6
import java.util.Scanner;
interface AntiaddictInterface{ //防沉迷接口
boolean check(int age)throws UnderAgeException; //抽象检查方法,抛出用户未成年异常
}
class UnderAgeException extends Exception{ //自定义未成年异常
public UnderAgeException(String message) { //有参构造方法
super(message); //调用原有父类构造方法
}
}
public class ThrowExceptionDemo { //测试类
public static void main(String[] args) { //主方法
//lambda表达式创建AntiaddictInterface对象,默认抛出原有异常
AntiaddictInterface ai =(a)->{
if(a<18) { //如果年龄小于18岁
throw new UnderAgeException("未满18周岁,开启防沉迷模式!"); //抛出异常
}else { //否则
return true; //验证通过
}
};
Scanner sc = new Scanner(System.in); //创建控制台扫描器
System.out.print("请输入年龄:"); //控制台提示
int age = sc.nextInt(); //获取用户输入的年龄
try { //因为接口方法抛出异常,所以此处必须捕捉异常
if(ai.check(age)) { //验证年龄
System.out.println("欢迎进入XX世界");
}
}catch(UnderAgeException e) { //控制台打印异常警告
System.out.println(e);
}
sc.close(); //关闭扫描器
}
}
语法:
类名::静态方法名
新的操作符“::”,中间无空格,左边表示方法所属的类名,右边是方法名,语法中方法名是没有括号的。
例题14.7
interface StaticMethodInterface{ //测试接口 例题14.7
int method(int a, int b); //抽象方法
}
public class StaticMethodDemo {
static int add(int x,int y) { //静态方法,返回两个参数相加的结果
return x +y; //返回相加结果
}
public static void main(String[] args) {
// TODO Auto-generated method stub
StaticMethodInterface sm= StaticMethodDemo::add; //引用StaticMethodDemo类的静态方法
int result = sm.method(15,16); //直接调用接口方法获取结果
System.out.println("接口方法结果:"+result); //输出结果
}
}
引用成员方法的语法:
对象名::成员方法名
操作符左侧必须是一个对象名,而不是类名。
例题14.8
import java.text.SimpleDateFormat; //例题14.8
import java.util.Date;
interface InstanceMethodInterface{ //测试创建接口
String method(Date date); //带参数的抽象方法
}
public class InstanceMethodDemo {
public String format(Date date) { //格式化方法
//创建日期格式化对象,并指定日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd");
return sdf.format(date); //返回格式化结果
}
public static void main(String[] args) {
// TODO Auto-generated method stub
InstanceMethodDemo demo = new InstanceMethodDemo(); //创建类对象
InstanceMethodInterface im = demo::format; //引用类对象的方法
Date date = new Date(); //创建日期对象
System.out.println("默认格式:"+date); //输出日期对象默认格式
System.out.println("接口输出的格式:"+im.method(date)); //输出经过接口方法处理过的格式
}
}
Iambda表达式有3种引用构造方法的语法,分别是引用无参数构造方法、引用有参构造方法和引用数构造方法
语法:
类名::new
注意:new关键字之后没有圆括号,也没有参数的定义
interface ConstructorsInterface1{ //构造方法接口
ConstructorsDemo1 action(); //调用无参方法
}
public class ConstructorsDemo1 { //测试类
public ConstructorsDemo1() { //无参构造方法
System.out.print("无参构造方法");
}
public ConstructorsDemo1(int a) { //有参构造方法
System.out.print("有参构造方法"+ a);
}
public static void main(String[] args) {
ConstructorsInterface1 ci = ConstructorsDemo1::new; //引用ConstructorsDemo1类的构造方法
ci.action(); //通过无参方法创建对象
}
}
引用有参构造方法的语法与引用无参构造方法一样。区别就是函数式接口的抽象方法是有参数的
例题14.11
interface ConstructorsInterface2{ //构造方法接口
ConstructorsDemo2 action(int i); //调用有参方法
}
public class ConstructorsDemo2 { //测试类
public ConstructorsDemo2(){ //无参构造方法
System.out.print("调用无参构造方法");
}
public ConstructorsDemo2(int i) { //有参构造方法
System.out.println("有参构造方法,参数为:"+i);
}
public static void main(String[] args) {
ConstructorsInterface2 a = ConstructorsDemo2::new; //引用ConstructorsDemo1类的构造方法
ConstructorsDemo2 b = a.action(123); //通过无参方法创建对象
}
}
语法;
类名[]::new
这个接口有以下两个泛型:
流处理有点类似数据库的 SQL 语句,可以执行非常复杂的过滤、映射、查找和收集功能,并且代码量很少。唯一的缺点是代码可读性不高。
对员工数据进行流处理
员工集合的详细数据如下
import java.util.ArrayList;
import java.util.List;
public class Employee {
private String name; //姓名
private int age; //年龄
private double salary; //工资
private String sex; //性别
private String dept; //部门
public Employee(String name, int age, double salary, String sex, String dept) {
super();
this.name = name;
this.age = age;
this.salary = salary;
this.sex = sex;
this.dept = dept;
}
@Override
public String toString() {
return "Employee [name=" + name + ", age=" + age + ", salary=" + salary + ", sex=" + sex + ", dept=" + dept
+ "]";
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public double getSalary() {
return salary;
}
public String getSex() {
return sex;
}
public String getDept() {
return dept;
}
static List getEmpList(){
List list=new ArrayList();
list.add(new Employee("老张",40,9000,"男","运营部"));
list.add(new Employee("小刘",24,5000,"女","开发部"));
list.add(new Employee("大刚",32,7500,"男","销售部"));
list.add(new Employee("翠花",28,5500,"女","销售部"));
list.add(new Employee("小马",21,3000,"男","开发部"));
list.add(new Employee("老王",35,6000,"女","人事部"));
list.add(new Employee("小王",21,3000,"女","人事部"));
return list;
}
}
方法如下:
Source——Generate ConStructor using Fields