函数式接口 - 15
一、函数式接口
有且仅有一个抽象方法的接口。
修饰符 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> 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对
象数据。
import java.util.function.Supplier; public class Demo08Supplier { private static String getString(Supplier<String> 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<Integer> 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<T> 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,
其数据类型由泛型决定。
Consumer 接口中包含抽象方法 void accept(T t) ,意为消费一个指定泛型的数据。
import java.util.function.Consumer; public class Demo09Consumer { private static void consumeString(Consumer<String> 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<String> one, Consumer<String> 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<String> one, Consumer<String> two, String[] array) { for (String info : array) { one.andThen(two).accept(info); // 姓名:迪丽热巴。性别:女。 } } }
Predicate接口
有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用
java.util.function.Predicate<T> 接口。
Predicate 接口中包含一个抽象方法: boolean test(T t) 。
import java.util.function.Predicate; public class Demo15PredicateTest { private static void method(Predicate<String> 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<String> one, Predicate<String> 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<String> one, Predicate<String> 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<String> 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<String> list = filter(array, s ‐> "女".equals(s.split(",")[1]), s ‐> s.split(",")[0].length() == 4); System.out.println(list); } private static List<String> filter(String[] array, Predicate<String> one, Predicate<String> two) { List<String> list = new ArrayList<>(); for (String info : array) { if (one.and(two).test(info)) { list.add(info); } } return list; } }
Function接口
java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,
后者称为后置条件.
Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。
import java.util.function.Function; public class Demo11FunctionApply { private static void method(Function<String, Integer> 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<String, Integer> one, Function<Integer, Integer> 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<String, String> one, Function<String, Integer> two, Function<Integer, Integer> three) { return one.andThen(two).andThen(three).apply(str); } }