一、函数式接口
有且仅有一个抽象方法的接口。
修饰符 interface 接口名称 {
public abstract 返回值类型 方法名称(可选参数信息);
// 其他非抽象方法内容
}
由于接口当中抽象方法的 public abstract 是可以省略的,所以定义一个函数式接口很简单:
public interface MyFunctionalInterface {
void myMethod();
}
@FunctionalInterface
public interface MyFunctionalInterface {
void myMethod();
}
public class Demo09FunctionalInterface {
// 使用自定义的函数式接口作为方法参数
private static void doSomething(MyFunctionalInterface inter) {
inter.myMethod(); // 调用自定义的函数式接口方法
}
public static void main(String[] args) {
// 调用使用函数式接口的方法
doSomething(() ‐> System.out.println("Lambda执行啦!"));
}
}
二、函数式编程
Lambda的延迟执行
性能浪费:

Lambda的更优写法

Lambda作为参数和返回值
三、常用函数式接口
Supplier接口
java.util.function.Supplier
接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对
象数据。
import java.util.function.Supplier;
public class Demo08Supplier {
private static String getString(Supplier function) {
return function.get();
}
public static void main(String[] args) {
String msgA = "Hello";
String msgB = "World";
System.out.println(getString(() ‐> msgA + msgB));
}
}
练习:求数组元素最大值
public class Demo02Test {
//定一个方法,方法的参数传递Supplier,泛型使用Integer
public static int getMax(Supplier sup){
return sup.get();
}
public static void main(String[] args) {
int arr[] = {2,3,4,52,333,23};
//调用getMax方法,参数传递Lambda
int maxNum = getMax(()‐>{
//计算数组的最大值
int max = arr[0];
for(int i : arr){
if(i>max){
max = i;
}
}
return max;
});
System.out.println(maxNum);
}
}
Consumer接口
java.util.function.Consumer 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,
其数据类型由泛型决定。
Consumer 接口中包含抽象方法 void accept(T t) ,意为消费一个指定泛型的数据。
import java.util.function.Consumer;
public class Demo09Consumer {
private static void consumeString(Consumer function) {
function.accept("Hello");
}
public static void main(String[] args) {
consumeString(s ‐> System.out.println(s));
}
}
默认方法:andThen
import java.util.function.Consumer;
public class Demo10ConsumerAndThen {
private static void consumeString(Consumer one, Consumer two) {
one.andThen(two).accept("Hello");
}
public static void main(String[] args) {
consumeString(
s ‐> System.out.println(s.toUpperCase()),
s ‐> System.out.println(s.toLowerCase()));
}
}
练习:格式化打印信息
import java.util.function.Consumer;
public class DemoConsumer {
public static void main(String[] args) {
String[] array = { "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男" };
printInfo(s ‐> System.out.print("姓名:" + s.split(",")[0]),
s ‐> System.out.println("。性别:" + s.split(",")[1] + "。"),
array);
}
private static void printInfo(Consumer one, Consumer two, String[] array) {
for (String info : array) {
one.andThen(two).accept(info); // 姓名:迪丽热巴。性别:女。
}
}
}
Predicate接口
有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用
java.util.function.Predicate 接口。
Predicate 接口中包含一个抽象方法: boolean test(T t) 。
import java.util.function.Predicate;
public class Demo15PredicateTest {
private static void method(Predicate predicate) {
boolean veryLong = predicate.test("HelloWorld");
System.out.println("字符串很长吗:" + veryLong);
}
public static void main(String[] args) {
method(s ‐> s.length() > 5);
}
}
默认方法:and
import java.util.function.Predicate;
public class Demo16PredicateAnd {
private static void method(Predicate one, Predicate two) {
boolean isValid = one.and(two).test("Helloworld");
System.out.println("字符串符合要求吗:" + isValid);
}
public static void main(String[] args) {
method(s ‐> s.contains("H"), s ‐> s.contains("W"));
}
}
默认方法:or
import java.util.function.Predicate;
public class Demo16PredicateAnd {
private static void method(Predicate one, Predicate two) {
boolean isValid = one.or(two).test("Helloworld");
System.out.println("字符串符合要求吗:" + isValid);
}
public static void main(String[] args) {
method(s ‐> s.contains("H"), s ‐> s.contains("W"));
}
}
默认方法:negate
import java.util.function.Predicate;
public class Demo17PredicateNegate {
private static void method(Predicate predicate) {
boolean veryLong = predicate.negate().test("HelloWorld");
System.out.println("字符串很长吗:" + veryLong);
}
public static void main(String[] args) {
method(s ‐> s.length() < 5);
}
}
练习:集合信息筛选
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class DemoPredicate {
public static void main(String[] args) {
String[] array = { "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男", "赵丽颖,女" };
List list = filter(array,
s ‐> "女".equals(s.split(",")[1]),
s ‐> s.split(",")[0].length() == 4);
System.out.println(list);
}
private static List filter(String[] array, Predicate one,
Predicate two) {
List list = new ArrayList<>();
for (String info : array) {
if (one.and(two).test(info)) {
list.add(info);
}
}
return list;
}
}
Function接口
java.util.function.Function 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,
后者称为后置条件.
Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。
import java.util.function.Function;
public class Demo11FunctionApply {
private static void method(Function function) {
int num = function.apply("10");
System.out.println(num + 20);
}
public static void main(String[] args) {
method(s ‐> Integer.parseInt(s));
}
}
默认方法:andThen
import java.util.function.Function;
public class Demo12FunctionAndThen {
private static void method(Function one, Function two) {
int num = one.andThen(two).apply("10");
System.out.println(num + 20);
}
public static void main(String[] args) {
method(str‐>Integer.parseInt(str)+10, i ‐> i *= 10);
}
}
练习:自定义函数模型拼接
1. 将字符串截取数字年龄部分,得到字符串;
2. 将上一步的字符串转换成为int类型的数字;
3. 将上一步的int数字累加100,得到结果int数字
import java.util.function.Function;
public class DemoFunction {
public static void main(String[] args) {
String str = "赵丽颖,20";
int age = getAgeNum(str, s ‐> s.split(",")[1],
s ‐>Integer.parseInt(s),
n ‐> n += 100);
System.out.println(age);
}
private static int getAgeNum(String str, Function one,
Function two,
Function three) {
return one.andThen(two).andThen(three).apply(str);
}
}