行为参数化

行为参数化即将行为方法通过参数的形式传递给方法,来实现特定的功能。行为参数化是为了应对多变的需求,而降低代码的冗余而提出的。行为参数化是一种编程的思想,即它的实现时通过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