1. 函数式接口
1. 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,可以有多个非抽象方法的接口
2. 函数式接口可以被隐式转换为 lambda 表达式
3. 函数式接口通常@FunctionalInterface注解标识
/** * 这是一个自定义的函数式接口 * @FunctionalInterface 用于检测一个接口是否为函数式接口 */ @FunctionalInterface public interface MyInterface { boolean method(); }
2. Lambda表达式
Lambda可以作为参数和返回值,此外匿名内部类没有class文件的概念,内存中即少加载一个文件
public class Lamda { public static void main(String[] args) { List<Apple> inventory = Arrays.asList(new Apple(100, "red"), new Apple(150, "green")); List<Apple> result = filter(inventory, apple -> apple.weight > 100); result.forEach(System.out::println); } public static List<Apple> filter(List<Apple> inventory, MyInterface iface) { List<Apple> result = new ArrayList<>(); for (Apple apple : inventory) { if (iface.method(apple)) { result.add(apple); } } return result; } /** * 这是一个自定义的函数式接口 * * @FunctionalInterface 用于检测一个接口是否为函数式接口 */ @FunctionalInterface public interface MyInterface { boolean method(Apple apple); } }
2.1 Lambda延迟加载
提升性能:有些代码在执行后,结果不一定被使用,从而造成性能浪费;例如:日志案例
public class LoggerLambda { public static void main(String[] args) { String msgA = "Hello "; String msgB = "world "; String msgC = "Java "; //只有level==1时,才会执行buildMessage(),返回拼接的字符串,不浪费性能 log(1, () -> msgA + msgB + msgC); } private static void log(int level, MessageBuilder builder) { if (level == 1) { System.out.println(builder.buildMessage()); } } @FunctionalInterface public interface MessageBuilder { String buildMessage(); //空参数,返回值为String } }
2.2 Lambda作用域
在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量;
3. 常用的API函数式接口
JDK 1.8 之前
- java.lang.Runnable
- java.util.concurrent.Callable
- java.security.PrivilegedAction
- java.util.Comparator
- java.io.FileFilter
- java.nio.file.PathMatcher
- java.lang.reflect.InvocationHandler
- java.beans.PropertyChangeListener
- java.awt.event.ActionListener
- javax.swing.event.ChangeListener
JDK 1.8 之后
函数式接口在java.util.function包下,参考这里
3.1 Predicate
java.util.function.Predicate<T>接口是判断型接口,主要用于判断是否满足某个谓词,API包含5个方法:
1. boolean test(T t)
2. default Predicate<T> and(Predicate<? super T> other)
3. dafault Predicate<T> or(Predicate<? super T> other)
4. default Predicate<T> negate()
5. static <T> Predicate<T> isEqual(Object targetRef)
public class ApplePredicate { public static void main(String[] args) { List<Apple> inventory = Arrays.asList( new Apple(100, "red", 1, "CN"), new Apple(150, "green", 2, "UK"), new Apple(200, "red", 3, "USA")); filter(inventory, apple -> apple.getNumber() > 2); filter2(inventory, apple -> apple.getNumber() > 1, apple -> apple.getWeight() > 100); Predicate<Apple> predicate = apple -> apple.getWeight() > 200; //谓词取反,negate代表苹果重量小于等于200的谓词 Predicate<Apple> negate = predicate.negate(); filter(inventory, negate); Apple apple = new Apple(100, "red", 1, "CN"); //筛选出和apple相同苹果的谓词 Predicate<Apple> predicate1 = Predicate.isEqual(apple); filter(inventory, predicate1).forEach(apple1 -> System.out.println(apple)); } /** * Predicate test() method demo * 筛选出满足谓词的苹果 * * @param inventory * @param predicate * @return */ public static List<Apple> filter(List<Apple> inventory, Predicate<Apple> predicate) { List<Apple> result = new ArrayList<>(); for (Apple apple : inventory) { if (predicate.test(apple)) { result.add(apple); } } return result; } /** * Predicate and() method demo * 筛选出同时满足两个谓词条件的苹果 * * @param inventory * @param predicate1 * @param predicate2 * @return */ public static List<Apple> filter2(List<Apple> inventory, Predicate<Apple> predicate1, Predicate<Apple> predicate2) { List<Apple> result = new ArrayList<>(); for (Apple apple : inventory) { Predicate<Apple> and = predicate1.and(predicate2); if (and.test(apple)) { result.add(apple); } } return result; } /** * Predicate or() method demo * 筛选出满足两个谓词条件中任意一个条件的苹果 * * @param inventory * @param predicate1 * @param predicate2 * @return */ public static List<Apple> filter3(List<Apple> inventory, Predicate<Apple> predicate1, Predicate<Apple> predicate2) { List<Apple> result = new ArrayList<>(); for (Apple apple : inventory) { Predicate<Apple> or = predicate1.or(predicate2); if (or.test(apple)) { result.add(apple); } } return result; } @Data @AllArgsConstructor @EqualsAndHashCode public static class Apple { private int weight; //苹果重量 private String color;//苹果颜色 private int number;//苹果编号 private String city;//苹果产地 } }
3.2 Consumer接口
java.util.function.Consumer<T>接口是消费型接口,与Suppier接口相反;包含两个方法:
1. void accept(T t)
2. default Consumer<T> andThen(Consumer<? super T> after)
public class ConsumerDemo { public static void main(String[] args) { List<Apple> inventory = Arrays.asList( new Apple(100, "red", 1, "CN"), new Apple(150, "green", 2, "UK"), new Apple(200, "red", 3, "USA")); //定义一个消费List<Apple>的接口,打印苹果的编号 Consumer<List<Apple>> consumer = apples -> { for (Apple apple : apples) { System.out.print(apple.getNumber()); } }; //定义一个消费List<Apple>的接口,打印苹果的产地 Consumer<List<Apple>> consumer2 = apples -> { for (Apple apple : apples) { System.out.print(apple.getCity()); } }; consumer.accept(inventory); consumer.andThen(consumer2).accept(inventory); } @Data @AllArgsConstructor @EqualsAndHashCode public static class Apple { private int weight; //苹果重量 private String color;//苹果颜色 private int number;//苹果编号 private String city;//苹果产地 } }
3.3 Function接口
java.util.function.Function<T,R>接口用来转化数据类型,T, R表示接口输入、输出的数据类型,相当于y=f(x),包含4个方法:
1. R apply(T t)
2. default <V> Function<T, V> andThen(Function<? super R, ? extends V> after)
3. default <V> Function<V, R> compose(Function<? super V, ? extends T> before)
4. static <T> Function<T, T> identity()
public class ConsumerDemo { public static void main(String[] args) { Function<Integer, Integer> function1 = i -> i + 1; Function<Integer, Integer> function2 = i -> i * i; //6 5+1=6 System.out.println(function1.apply(5)); //25 5*5=25 System.out.println(function2.apply(5)); //36 (5+1)*(5+1)=36 System.out.println(function1.andThen(function2).apply(5)); //26 (5*5)+1=26 System.out.println(function1.compose(function2).apply(5)); } }
3.4 BiFunction接口
java.util.function.Function<T,U,R> 接口用来转化数据类型,T, U表示接口输入的数据类型、R表示输出的数据类型,相当于z=f(x,y);包含2个方法:
1. R apply(T t, U u);
2. default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after)
3.5 Supplier接口
java.util.function.Supplier<T>接口是供给型接口,包含一个无参的方法:
T get()
这就意味这Lambda表达式需要对外提供一个符合泛型类型的对象数据;个人理解:Supplier类似于工厂,提供了一个规范,用户DIY具体实现;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import java.util.function.Supplier; public class SuppilerDemo { public static void main(String[] args) { int[] arr = {6, 4, 3, 8, 9}; System.out.println(getMax(() -> { int max = arr[0]; for (int i : arr) { max = max > i ? max : i; } return max; })); } /** * 提供返回最大值的功能 * @param supplier * @return */ public static int getMax(Supplier<Integer> supplier) { return supplier.get(); } @Data @AllArgsConstructor @EqualsAndHashCode public static class Apple { private int weight; //苹果重量 private String color;//苹果颜色 private int number;//苹果编号 private String city;//苹果产地 } }