行为参数化
行为参数化即将行为方法通过参数的形式传递给方法,来实现特定的功能。行为参数化是为了应对多变的需求,而降低代码的冗余而提出的。行为参数化是一种编程的思想,即它的实现时通过Java8提供的一些改变得以实现,在Java8之前,不能将方法作为参数传递给另一个方法。
行为参数化解决了多变的需求;
行为参数化实现了方法之间的解耦,功能之间更像是模块的方式,方便的增加和删除;
行为参数化降低代码的冗余,实现高效,便捷的开发。
lambda表达式
lambda表达式和行为参数化的关系,lambda表达式为行为参数化提供了更简洁,遍历的书写方式,对于行为参数化的实现,我们需要准备相应的条件,然后通过方法的传入来实现所需的功能,但是对于一个方法的实现,我们需要将整个方法的实现全部传递进去,使得代码的可观性降低,附带太多的冗余(相对lambda的写法),lambda表达式以更简洁的方式来实现前期的功能。
具体例子详解:
接口(行为接口):filterStudent
类:Students,FilterIdStudent(行为实现类),FilterStudent(业务实现类)
filterStudent:
package com.dong.interfaces;
import com.dong.bean.Students;
public interface filterStudent {
public boolean filter(Students student);
}
Students:
package com.dong.bean;
public class Students {
private String name;
private Integer id;
private String address;
public Students(String name, Integer id, String address) {
super();
this.name = name;
this.id = id;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
FilterIdStudent:
package com.dong.service;
import java.util.ArrayList;
import java.util.List;
import com.dong.bean.Students;
import com.dong.interfaces.filterStudent;
public class FilterIdStudent implements filterStudent {
@Override
public boolean filter(Students student) {
// TODO Auto-generated method stub
return (student.getId().intValue()>1000);
}
}
FilterStudent
package com.dong.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.dong.bean.Students;
public class FilterStudent {
public static List<Students> filterstudent(List<Students> students,FilterIdStudent p){
List<Students> results = new ArrayList<>();
for(Students stu : students) {
if(p.filter(stu)) {
results.add(stu);
}
}
return results;
}
public static void main(String[] args) {
Students stu1 = new Students("ld", 999, "china");
Students stu2 = new Students("lx", 1023, "china");
Students stu3 = new Students("lds", 1293, "china");
List<Students> stus = new ArrayList<>();
stus.add(stu1);stus.add(stu2);stus.add(stu3);
FilterIdStudent fis = new FilterIdStudent();
List res = filterstudent(stus, fis);
System.out.println(res.toString());
for(int i=0;i<res.size();i++) {
Students st = (Students) res.get(i);
System.out.println(st.getName());
}
}
}
Run As Result:
[com.dong.bean.Students@6bc168e5, com.dong.bean.Students@7b3300e5]
lx
lds
FilterStudent的lambda的实现变动:
接口的变化:(filterStudent接口不需要,FilterIdStudent类也不需要了,Students类不变,不需要单独实现filterStudent2接口的具体类)
使用泛型,可以将对象的类型不局限于具体的Studnets.
package com.dong.interfaces;
public interface filterStudent2<T> {
public boolean filter(T t);
}
FilterStudent类的变化:
package com.dong.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.dong.bean.Students;
import com.dong.interfaces.filterStudent2;
public class FilterStudent {
public static <T> List<T> filter(List<T> list,filterStudent2<T> p){
List<T> result = new ArrayList<>();
for(T e : list) {
if(p.filter(e)) {
result.add(e);
}
}
return result;
}
public static void main(String[] args) {
List<Students> stus = Arrays.asList(new Students("ld", 999, "china"),
new Students("lx", 1023, "china"),
new Students("lds", 1293, "china"));
List<Students> rest =
filter(stus, (Students student) -> student.getId().intValue()>1000);
System.out.println(rest.toString());
}
}
Run as Result:
[com.dong.bean.Students@24273305, com.dong.bean.Students@5b1d2887]
lambda表达式的理解
lambda可以理解为简洁地表示可传递的匿名函数的一种方式,没有名称,有参数列表,函数主体,返回类型,同时lambda表达式可以看做是接口的实现类。lambda表达式没有return语句,它根据语句的结果来推断出返回类型,语句没有结果的话,则是void。
格式:
(Students student) -> student.getId().intValue()>1000)
lambda的使用条件:
lambda需要在函数式接口上使用Lambda表达式。什么样的接口是函数式接口?函数式接口需要满足接口满足以下条件:
⑴只定义一个抽象方法的接口,eg:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
@FunctionalInterface注解的作用:
⑴该注解只能使用在有且仅有一个抽象方法的接口上;
⑵JDK8接口中的静态方法和默认方法,都不算是抽象方法。
⑶该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
JavaAPI已有的函数式接口:
⑴Predicate<T>接口,定义test抽象方法,该方法接受泛型T对象,返回boolean
⑵Consumer<T>接口,定义accept抽象方法,接受泛型T对象,返回void
⑶Function<T,R>接口,定义apply抽象方法,接受泛型T对象,返回泛型R的对象;等等等
(图片只是部分类文件)
方法引用
方法引用可以看做是对某些Lambda的更近一步的简洁化,使的代码在特定的场合更具有可读性,“如果一个lambda表示的只是“直接调用这个方法”,则最好使用明后才能来调用它,而不是去描述如何调用它。”<--来自《Java8实战》。使用方式:目标引用放在分隔符::前,方法的名称放在后面。
(Students student) -> student.getId() 等效于 Student::getId
(String s ) -> System.out.println(s) 等效于 System.out::println
内容参考《Java8实战》
参考 :https://blog.csdn.net/aitangyong/article/details/54137067