Java8新特性:函数式接口

Java8新特性:函数式接口

一 什么是函数式接口:

通过java8新特性:Lambda表达式这篇博客可以知道,Lambda表达式需要将箭头操作符左右两侧的内容传递给只含有一个抽象方法的接口(即函数式接口)。

1.1 函数式接口特点:

1)只包含一个a抽象a方法的n接口,称为函数式接口。
2) 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方
法上进行声明)。
3) 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

java8新特性:Lambda表达式这篇博客的4.1部分的MyFun就是一个函数式接口,我们通过Lambda表达式实现对一个数的具体运算。

@FunctionalInterface
public interface MyFun {

	public Integer getValue(Integer num);
	
}

二 Java内置四大核心函数式接口

Java8新特性:函数式接口

Consumer<T> : 消费型接口(一参,无返回值)
     void accept(T t);
 
Supplier<T> : 供给型接口(无参,有返回值)
     T get(); 
 
Function<T, R> : 函数型接口(一参,有返回值)
     R apply(T t);
 
Predicate<T> : 断定型接口(一参,boolean返回值)
     boolean test(T t);

关于这四个接口内抽象方法的记忆,博主提供一个方法:对于消费型接口Consumer<T>,消费就需要给钱,别人接受,就是accept方法;对于 供给型接口Supplier<T>,别人得到供给,对应的就是get方法;对于函数型接口Function<T,R>,别人需要应用你的函数,对应的就是apply方法;对于断定型接口Predicate<T>,别人需要测试你的断言,对应的就是test方法。

4.1 四大内置函数式接口使用案例

先面的代码从下往上看,每一个接口的测试都需要一个接口作为形参的方法,然后使用Lambda表达式传递,对此方法进行测试。

	//Predicate<T> 断言型接口:
	@Test
	public void test4(){
		List<String> list = Arrays.asList("Hello", "beautiful", "Lambda", "www", "ok");
		List<String> strList = filterStr(list, (s) -> s.length() > 3);
		
		for (String str : strList) {
			System.out.println(str);
		}
	}
	
	//需求:将满足条件的字符串,放入集合中
	public List<String> filterStr(List<String> list, Predicate<String> pre){
		List<String> strList = new ArrayList<>();
		
		for (String str : list) {
			if(pre.test(str)){
				strList.add(str);
			}
		}
		
		return strList;
	}
	
	//Function<T, R> 函数型接口:
	@Test
	public void test3(){
		String newStr = strHandler("\t\t\t 我要学会函数式接口   ", (str) -> str.trim());
		System.out.println(newStr);
		
		String subStr = strHandler("我要学会函数式接口", (str) -> str.substring(5));
		System.out.println(subStr);
	}
	
	//需求:用于处理字符串的方法
	public String strHandler(String str, Function<String, String> fun){
		return fun.apply(str);
	}
	
	//Supplier<T> 供给型接口 :
	@Test
	public void test2(){
		List<Integer> numList = getNumList(10, () -> (int)(Math.random() * 100));
		
		for (Integer num : numList) {
			System.out.println(num);
		}
	}
	
	//需求:产生指定个数的整数,并放入集合中
	public List<Integer> getNumList(int num, Supplier<Integer> sup){
		List<Integer> list = new ArrayList<>();
		
		for (int i = 0; i < num; i++) {
			Integer n = sup.get();
			list.add(n);
		}
		
		return list;
	}
	
	//Consumer<T> 消费型接口 :
	@Test
	public void test1(){
		happy(10000, (m) -> System.out.println("你们刚哥喜欢大宝剑,每次消费:" + m + "元"));
	} 
	
	public void happy(double money, Consumer<Double> con){
		con.accept(money);
	}

五 其他函数式接口

可以发现,四大内置函数式接口内的抽象方法都是一个参数,没有多参的。事实上,Java8还提供了其他的函数式接口,其中有多参的,如下图。只是他们的使用频率没有四大内置函数式接口的高。

Java8新特性:函数式接口

六 函数式接口总结

Lambda表达式取代匿名内部类传递给接口(此接口为某个方法的形参)作为某方法的形参时,要求接口只能有一个抽象方法,即为函数式接口。为此,java8为我们提供了一些函数式接口,这样我们就不需要再像Myfun接口那样,每次使用接口作为形参的方法时,都要写一个接口。(即java8给我们提供了一些现成的函数是接口)。四大内置函数式接口分别对应于一参无返回值;无参有返回值;一参有返回值;一参boolean返回值这四种情况。