Lambda运用的问题
Demo班主任想了解一下各个同学的相关情况
- 1.找出来自成都的有哪些同学
定义一个找出成都同学函数
//找出成都的同学
public List<Student> findStudentsAndAreaByChengDu(List<Student> students){
List<Student> result = new ArrayList<Student>();
for(Student temp:students){
if("成都".equals(temp.getAge())) {
result.add(temp);
}
}
return result;
}
班导现在又想知道来自北京的有哪些同学,那代码执行优化一下
可以动态传地区参数。
//动态参数化传入查询的地区
public List<Student> findStudentsAndAreaByChengDu(List<Student> students,String thisarea){
List<Student> result = new ArrayList<Student>();
for(Student temp:students){
if(thisarea.equals(temp.getAge())) {
result.add(temp);
}
}
return result;
}
现在需要知道年龄等于20岁的同学
我们选择重新声明一个动态传入年龄参数的函数
//查询年龄等于20的学生
public List<Student> findStudentsAndAgeBy20(List<Student> students,int thisage){
List<Student> result = new ArrayList<Student>();
for(Student temp:students){
if(thisage==temp.getAge()) {
result.add(temp);
}
}
return result;
}
发现两个方法里面的代码是不是很像,有很多重复的代码
想到JAVA的设计模式
策略模式
定义一个接口,用来进行过滤的接口
//接口用来过滤
public interface StudentFilter {
boolean test(Student stu);
}
我们可以实现这个接口,去完成不同的需求,如:
public class StudentAreaFilter implements StudentFilter{
@Override
public boolean test(Student stu) {
// 查询成都地区的人
return "成都".equals(stu.getArea());
}
}
public class StudentAgeFilter implements StudentFilter{
@Override
public boolean test(Student stu) {
// 查询年龄大于20的学生
return stu.getAge()>20;
}
}
上面定义了两种查询条件,都是实现了StudentFilter接口,那我们再看看主方法
public List<Student> findStudentsByFilter(List<Student> students,StudentFilter stufilter){
List<Student> result = new ArrayList<Student>();
for(Student temp:students){
if(stufilter.test(temp)) {
result.add(temp);
}
}
return result;
}
上面的核心代码就是stufilter.test(temp)
;这个就是查询条件逻辑实现方法;要查询某个业务,只需要把相关业务的接口实现传给这个主方法就行了。
//查询成都地区的学生
List<Student> areaStudents = findStudentsByFilter(Students,new StudentAreaFilter());
//查询年龄大于20的学生
List<Student> ageStudents = findStudentsByFilter(Students,new StudentAgeFilter ());
如有别的查询需求,只要实现StudentPredicate接口就行了。
但这点也是个缺点,每个需求都要去写相关的接口实现。
匿名类
为了解决接口实现太多,可以采用匿名类去解决,再来优化一下
//接口
public interface StudentFilter {
boolean test(Student stu);
}
//主方法实现
public List<Student> findStudentsByFilter(List<Student> students,StudentFilter stufilter){
List<Student> result = new ArrayList<Student>();
for(Student temp:students){
if(stufilter.test(temp)) {
result.add(temp);
}
}
return result;
}
//查询成都地区的学生
List<Student> areaStudents = findStudentsByFilter(Students,new StudentFilter () {
@Override
public boolean test(Student stu) {
return "成都".equals(stu.getArea());
}
});
这种方式大大的减少了接口实现类,需要什么业务需求,直接在调用方法的时候建立匿名类去实现就行了。匿名类的方式,我们的大佬觉得还是不够简洁,所以Java8
中新增了Lambda
表达式。
//接口
public interface StudentFilter {
boolean test(Student stu);
}
//主方法实现
public List<Student> findStudentsByFilter(List<Student> students,StudentFilter stufilter){
List<Student> result = new ArrayList<Student>();
for(Student temp:students){
if(stufilter.test(temp)) {
result.add(temp);
}
}
return result;
}
//查询成都地区的学生
List<Student> areaStudents = findStudentsByFilter(Students,(Student stu) -> "成都".equals(stu.getArea()));
什么是Lambda?
上面这个(Student stu) -> "成都".equals(stu.getArea())
就是我们的Lambda表达式,进一步我们可以提取它为一个参数,而参数的类型就是一个接口(上面为StudentFilter
)
1.一个Java变量,我们可以赋给其一个“值”。
int myint = 520;
String mystr = "hello world";
Boolean myboolean = mystr.startWith('h');
2.如果你想把一块代码赋给一个Java变量,应该怎么做呢?


3.但是这里仍然有一个问题,就是变量aBlockOfCode的类型应该是什么?
所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是”那段代码“
比如上面的:(Student stu) -> "成都".equals(stu.getArea())
,需要是这个接口的实现简而言之就是Lambda表达式本身就是一个接口的实现。

这种只有一个接口函数需要被实现的接口类型,我们叫它
函数式接口
。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成"非函数接口”,我们可以在这个上面加上一个声明@FunctionalInterface
, 这样别人就无法在里面添加新的接口函数了:
这样,我们就得到了
一个完整的Lambda表达式声明
:
回到上面的例子

文章参考
https://www.jianshu.com/p/888936ef9e23
https://www.zhihu.com/question/20125256
网友评论