JAVA8的新特性之函数式接口

1、Lambda表达式使用的前提,就是接口必须是一个函数式接口
2、定义
在接口中,只有一个抽象方法
3、检查是否是函数式接口用的注解
@FunctionalInterface
如果不是函数式接口,编译报错
4、函数式接口理解
(1)函数:更想让他表达的是方法的内容,由于方法不在任何类中,所以称为函数
(2)函数式接口:其实想表达的是一个函数的声明
5、作用:
使用函数式接口表达方法的声明:使用函数式接口的实现类对象表示函数的实现
6、使用原因:
java中不支持将函数作为一个数据,也就不能实现将这个函数进行各种传递,也就不能作为对象的成员变量存在
只能方法外加上一层接口的声明,将来可以传递方法所在接口的实现类对象,来间接传递方法内容。

package com.ujiuye.demos;

public class Demo_1 {
//	函数式接口的理解
	public static void main(String[] args) {
		/*Inter_1 in = new Inter_1() {
		
			@Override
			public void show() {
				System.out.println("hello");
			}
		};*/
		test_1(()->System.out.println("hello"));
	}
	
	public static void test_1(Inter_1 in) {
		in.show();
	}
}

interface Inter_1{
	public abstract void show();
}

常用的内置性函数式接口

1、java8中,提供一些常用的函数式接口,在使用类似功能的时候,不需要自己再去定义函数式接口了,直接使用java8中提供的内置型函数式接口。
2、罗列

Consumer 消费型接口
 void accept(T t);
 Supplier 供给型接口
 T get();
 Function<T,R> 函数型接口
 R apply(T t);
 Predicate:断言型接口
 boolean test(T t);

消费型接口

1、Consumer
2、抽象方法 void accept(T t)
3、作用:
(1)当某个函数可以接收一个数据,并且处理这个数据,处理完之后,不需要返回值,就可以使用消费型接口
(2)以前只能传递的是要处理的数据,现在传递处理数据的方式

package com.ujiuye.demos;

import java.util.function.Consumer;

public class Demo_2 {
//	消费型接口
	public static void main(String[] args) {
		/*Consumer<Integer> con = (m) -> {
			m *= 12;
			System.out.println(m);
		};*/
//		简单使用
		Consumer<String> con1 = (m)->System.out.println(m);
		con1.accept("hello");
		
		Consumer<Integer> con = new Consumer<Integer>() {
			@Override
			public void accept(Integer m) {
				m *= 12;
				System.out.println(m);
			}
		};
		
		test(con,"Ipone12");
//		将方法的实现作为传递的对象
		test((m)->System.out.println(m), "Ipone12");
	}

	public static void test(Consumer<Integer> con, String str) {
		con.accept(500);
		System.out.println(str);
	}

	public static void test(int a) {
		int b = a + 1;
		a = b * a;
		System.out.println(a);
	}
}

方法引用

1、写 一个函数式接口时,方法的实现(Lambda体),已经被某个其他类的对象给实现了,就不需要在lambda体中,再次调用这个实现,可以直接使用这个已经定义好的方法。
2、格式:
普通方法
函数式接口 名称 = 对象名 ::方法名称
静态方法
函数式接口 名称 = 类名 ::方法名称
构造方法
函数式接口 名称 = 类名 ::new;
3、作用:
把已经实现的方法,作为一个数据,作为实现类对象,赋值给某个函数式接口的引用
可以把这个引用当做方法的返回值,也可以作为方法的实际参数进行传递
4、本质:
可以把任意一个方法,作为函数接口的一个实现类对象

package com.ujiuye.demos;

import java.util.function.Consumer;

public class Demo_3 {
	public static void main(String[] args) {
		Inter_3 in33 = new Inter_3() {
			@Override
			public void show(String x) {
				System.out.println(x);
			}

		};
		in33.show("匿名内部类实现的");

		Inter_3 in3 = (x) -> System.out.println(x);
		in3.show("lambda体实现的");
//		方法引用
		Test t = new Test();
		Inter_3 in4 = t::test;
		in4.show("我是通过方法引用实现的");

		Inter_3 in5 = System.out::println;
		in5.show("我比较厉害");
//		静态方法的方法引用
		Inter_3 in6 = Test::test_1;
		in6.show("你好");
//		构造方法的方法引用
		Inter_3 in7 = Test::new;
		in7.show("函数式接口来借用一下你的方法");
//		 作为一个实参进行传递
		test(Test::new,"ipone12");
	}
	
	public static void test(Consumer<Integer> con, String str) {
		con.accept(500);
		System.out.println(str);
	} 
	
}

interface Inter_3 {
	public void show(String str);
}

class Test {
	public Test() {
		
	}
	public Test(String str) {
		str += "我是构造方法中的执行逻辑";
		System.out.println(str);
	}
	
	public void test(String x) {
		System.out.println(x);
	}

	public  Test(Integer x) {
		System.out.println(x);
	}
	public static void test_1(String x) {
		x += 1000000;
		System.out.println(x);
	}
}

供给型接口

1、Supplier
2、供给型接口
3、抽象方法,T get()
4、作用
如果需要定义函数,可以生产一个数据,这个函数可以当做一个数据进行传递,就可以使用供给型接口

package com.ujiuye.demos;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

public class Demo_4 {
//	供给型接口
	public static void main(String[] args) {
//		简单使用
		Supplier<Integer> sup = new Supplier<Integer>() {

			@Override
			public Integer get() {
				int a = (int) (Math.random() * 100);
				return a;
			}
		};
		Integer integer = sup.get();
		System.out.println(integer);
		Supplier<Integer> sup1 = () -> {
			int a = (int) (Math.random() * 100);
			return a;
		};
		Integer integer2 = sup1.get();
		System.out.println(integer2);

//		调用方法,传入生产数据的方式,和个数
		Supplier<Integer> sup2 = () -> {
			int a = (int) (Math.random() * 100);
			return a;
		};
		List<Integer> list = getNum(sup, 10);
		for (Integer integer3 : list) {
			System.out.println(integer3);
		}
	}

	public static List<Integer> getNum(Supplier<Integer> sup, int n) {
		List<Integer> list = new ArrayList<Integer>();
		for (int i = 0; i < n; i++) {
			list.add(sup.get());
		}
		return list;
	}

}

函数型接口

1、Function<T,R>
2、名称:函数型接口
3、抽象方法 R apply(T t)
4、作用:
如果需要定义一个函数,接口一个数据将数据进行处理,完成之后,还能返回一个结果,就可以使用函数型接口
5、提供功能
Function andThen(Function f2)
在调用者处理完之后,再将处理后的结果作为参数中的函数式接口的参数再进行下一步的处理

package com.ujiuye.demos;

import java.util.function.Function;

public class Demo_5 {
//函数型接口
	public static void main(String[] args) {
//		简单使用
		Function<String, Integer> fun1 = new Function<String, Integer>() {
			@Override
			public Integer apply(String t) {
				int length = t.length();
				return length;
			}
			
		};
		Integer apply = fun1.apply("成事不足败事有余");
		System.out.println(apply);
//		
		Function<String, Integer> fun2 = (x)->{
			int y = x.length();
			return y;
		};
		Integer apply2 = fun2.apply("我要迎娶白富美");
		System.out.println(apply2);
//		调用方法
		Function<String, Integer> fun3 = (x) -> {
			int indexOf = x.indexOf("接口");
			return indexOf;
		};
		int func = func(fun3,"函数式接口");
		System.out.println(func);
		System.out.println("------andThen-------");
//		
		Function<String, Integer> fun4 = (x)->x.length();
		Function<Integer, Integer> fun5 = x -> x += 10;
		int funcAndThen = funcAndThen(fun4, fun5, "北京欢迎你");
		System.out.println(funcAndThen);
	}
	
	public static int funcAndThen(Function<String, Integer> fun,Function<Integer, Integer> fun1,String str) {
//		 fun.apply(str);
//		先将fun处理str后的结果,作为fun2的参数传递进去
		Integer apply = fun.andThen(fun1).apply(str);
		return apply;
	}
	
	
	public static int func(Function<String, Integer> fun,String str) {
		Integer apply = fun.apply(str);
		return apply;
	}
}

断言型接口

1、Predicate
2、名称:断言型接口
3、抽象方法
boolean test(T t)
4、作用:
如果需要定义一个函数,接收一个数据进行相对应的判断,返回一个boolean的结果,就可以使用断言型接口
5、提供功能
and(Predicate pre)
or(Predicate pre)
negate():

package com.ujiuye.demos;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class Demo_6 {
//	断言型接口
	public static void main(String[] args) {
//		简单写法
		Predicate<String> pre = (s) -> {
			return s.startsWith("成");
		};
		boolean test = pre.test("成都");
		System.out.println(test);
//		
		List<String> list = new ArrayList<>();
		list.add("李广");
		list.add("陈赫");
		list.add("李晨");
		list.add("蔡徐坤");
		list.add("范冰冰");
		list.add("张子涵");
		list.add("李云龙");
		list.add("易烊千玺");
		list.add("上官端木");
		list.add("司马相如");
		System.out.println(list);
//		
		Predicate<String> pre1 = x -> x.length() == 2;
		List<String> newlist1 = filterName(pre1, list);
		for (String string : newlist1) {
			System.out.println(string);
		}
		System.out.println("Jjjjjjjjjjjjjjjjjjjjjjjjjjjjj");
		Predicate<String> pre2 = x -> x.startsWith("李");
		List<String> newlist2 = filterName(pre2, list);
		for (String string : newlist2) {
			System.out.println(string);
		}
		System.out.println("--------and--------------");
		Predicate<String> pre3 = x -> x.length() == 2;
		Predicate<String> pre4 = x -> x.startsWith("李");
		List<String> newlist3 = filterAnd(pre3, pre4, list);
		for (String string : newlist3) {
			System.out.println(string);
		}

		System.out.println("--------or--------------");
		Predicate<String> pre5 = x -> x.length() == 2;
		Predicate<String> pre6 = x -> x.startsWith("李");
		List<String> newlist4 = filterOr(pre5, pre6, list);
		for (String string : newlist4) {
			System.out.println(string);
		}
		System.out.println("--------negate--------------");
		Predicate<String> pre7 = x -> x.length() == 2;
		List<String> newlist5 = filterNegate(pre7, list);
		for (String string : newlist5) {
			System.out.println(string);
		}
	}
//	negate();  !
	public static List<String> filterNegate(Predicate<String> pre, List<String> list) {
//		新建一个集合用来存储,过滤后的数据
		List<String> newlist = new ArrayList<String>();
		for (String str : list) {
			if (pre.negate().test(str)) {
				newlist.add(str);
			}
		}
		return newlist;
	}
//	or方法
	public static List<String> filterOr(Predicate<String> pre, Predicate<String> pre1, List<String> list) {
//		新建一个集合用来存储,过滤后的数据
		List<String> newlist = new ArrayList<String>();
		for (String str : list) {
//			在调用者判断之后,再由参数中的断言型接口对象再进行判断,返回的是两个断言型接口对象都满足的情况
			if (pre.or(pre1).test(str)) {
				newlist.add(str);
			}
		}
		return newlist;

	}

//	and方法
	public static List<String> filterAnd(Predicate<String> pre, Predicate<String> pre1, List<String> list) {
//		新建一个集合用来存储,过滤后的数据
		List<String> newlist = new ArrayList<String>();
		for (String str : list) {
//			在调用者判断之后,再由参数中的断言型接口对象再进行判断,返回的是两个断言型接口对象都满足的情况
			if (pre.and(pre1).test(str)) {
				newlist.add(str);
			}
		}
		return newlist;

	}

	public static List<String> filterName(Predicate<String> pre, List<String> list) {
//		新建一个集合用来存储,过滤后的数据
		List<String> newlist = new ArrayList<String>();
		for (String str : list) {
			if (pre.test(str)) {
				newlist.add(str);
			}
		}
		return newlist;
	}

}