4.1lambda表达式
14.1.1lambda表达式简介
lambda表达式可以用非常少的代码实现抽象方法。lambda表达式不能独立执行,因此必须实现函数式接口,并且会返回一个函数式接口的对象。lambda表达式的语法非常特殊。
如下
()->结果表达式
参数->结果表达式
(参数1,参数2...参数n)->结果表达式
lambda表达式的语法非常抽象,并且有着非常强大的自动化功能,如自动识别泛型、自动数据类型转换等,
lambda表达式语法用如下方式理解:
() -> {代码块}
这个方法 按照 这样的代码来实现
14.1.2lambda表达式实现函数氏接口、
例题1
例题2
package 十四;
interface AddInt{
int add(int a,int b);
}
public class ParamDemo {
public static void main(String[] args) {
//使用匿名内部类
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));
}}
package 十四;
interface CheckGrade{
String check(int grade);//查询成绩结果
}
public class GradeDemo {
public static void main(String[] args) {
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~79
return"成绩为中"; //输出成绩为中
}else if (n>0&&n<60) { //如果成绩小于60
return "成绩为差"; //输出成绩为差
}else { //其他数字不是有效成绩
return"成绩无效"; //输出成绩无效
}
}; //不要丢掉lambda语句后的分号
System.out.println(g.check(89)); //输出查询结果
}
}
方法的引用
1.引用静态方法
语法:
类名::静态方法名
这个语法中出现了一个新的操作符“::”,这是由两个英文冒号组成的操作符,冒号之间没有空格。这个操作符左边表示方法所属的类名,右边是方法名。需要注意的是,这个语法中方法名是没有圆括号的。
2.引用成员方法
语法:
对象名::成员方法名
与引用静态方法语法不同,这里操作符左侧的必须是一个对象名,而不是类名。这种语法也可以达到抽象方法按照类成员方法逻辑来实现的目的。
3.引用泛型方法
泛型是Java开发经常使用到的功能,“::”操作符支持引用带泛型的方法。除方法外,“::”操作符也支持引用带泛型的类。
4.引用构造方法
(1)引用无参构造方法
语法:
类名::new
(2)引用有参构造方法
引用有参构造方法的语法与引用无参构造方法一样。区别就是函数式接口的抽象方法是有参数的。
使用lambda 表达式引用有参数的构造方法
创建函数式接口和测试类。测试类创建一个无参构造方法和一个有参构造方法。接口抽象方法返回值为测试类对象,并且方法参数结构要和测试类有参构造方法参数一致。使用引用构造方法语法创建接口对象,调用接口对象方法创建测试类对象,查看输出结果。
(3)引用数组构造方法
语法:
类名[]::new
例题14.8
创建函数式接口和测试类,在接口中定义抽象方法method(),在测试类中编写一个可以用来实现抽象方法的成员方法——format()方法。在main()方法中创建接口对象,并使用引用成员方法的语法让接口对象的抽象方法按照测试类的format()方法来实现。
package 十四;
import java.text.SimpleDateFormat;
import java.util.Date;
interface MetodDemoInterface{ //创建测试接口
String method(Date date); //带参数的抽象方法
}
public class MethodDemo {
public String format(Date date) { //格式化方法
//创建日期格式化对象,并指定日期格式
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(date); //返回格式化结果
}
public static void main(String[] args) {
MethodDemo demo =new MethodDemo(); //创建类对象
MetodDemoInterface im =demo::format; //引用类对象的方法
Date date =new Date(); //创建日期对象
System.out.println("默认格式:"+date); //输出日期对象默认格式
System.out.println("接口输出的格式"+im.method(date));//输出经过接口方法处理过的格式
}
}
14.3流处理
package 十四;
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;
}
//重写toString()方法,方便打印员工信息
@Override
public String toString() {
return "Employee [name=" + name + ", age=" + age + ", salary=" + salary + ", sex=" + sex + ", dept=" + dept
+ "]";
}
//以下是员工属性的getter方法
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<Employee> getEmpList(){ //提供数据初始化方法
List<Employee> list = new ArrayList<Employee>(); //添加员工数据
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,6000,"男","开发部"));
list.add(new Employee("老王",35,6000,"女","人事部"));
list.add(new Employee("小王",21,3000,"女","人事部"));
return list;
}}
14.3.1stream接口简介
流处理的接口都定义在Java.util.stream包下。
14.3.3Collectors类
Collectors类为收集器类,该类实现了Java.util.Collector接口,可以将stream流对象进行各种各样的封装、归集、分组等操作。
14.3.4数据过滤
数据过滤就是在杂乱的数据中筛选出需要的数据,类似SQL语句中的WHERE关键字,给出一定的条件,将符合条件的数据过滤并展示出来。
例题17
package 十四;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamDemo {
public static void main(String[] args) {
List<Employee> list = Employee.getEmpList();
Stream<Employee> stream = list.stream();
//筛选年龄大于30岁的员工
stream = stream.filter(a -> a.getAge()>30);
List<Employee> result = stream.collect(Collectors.toList());
for(Employee e : result) {
System.out.println(e);
}
}
}
限制条数
//限制条数
stream = stream.limit(2);
14.3.5数据映射
数据的映射和过滤概念不同:过滤式在流中找到符合条件的元素,映射是在流中获得具体的数据。
14.3.6数据查找
本节所讲的数据查找并不是在流中获取数据(这属于数据过滤),而是判断流中是否符合条件的数据,查找的结果是一个boolean值或一个Optional类的对象。本节将讲解allMatch()、anyMatch()、noneMatch()和findFirst()这4个方法。
14.3.7数据收集
数据收集可以理解为高级的“数据过滤+数据映射”,是对数据的深加工。本节将讲解两种实用场景:数据统计和数据分组。
1数据统计
数据统计不仅可以筛选出特殊元素,还可以对元素的属性进行统计计算。这种复杂的统计操作不是由Stream实现的,而是由Collectors收集器实现的,收集器提供了非常丰富的API,有着强大的数据挖掘能力。