vlambda博客
学习文章列表

【03】四大函数式接口


一个接口中有且仅有一个抽象方法(注:可以包含多个默认方法及静态方法)

如果要自定义一个函数式接口的时候可以使用@FunctionalInterface标识接口为函数式接口,被@FunctionalInterface标识的接口  如果出现一个以上的抽象方法  注解会报错,用于提示


常见的函数式接口

Function<T, R> -> R apply(T t) : 传入一个类型T返回类型R 


Lambda : change(1, x -> x + 3);  

  • 本次调用为传入int 返回int

方法引用 : change("123", Integer::parseInt); 

  • 本次调用为传入String 返回 Integer

public static <T, R> R change(T t, Function<T, R> function) { return function.apply(t);}

进阶方法

  • andThen : 先把参数作用于第一个函数,结果传递给第二个函数

如:Function<String, String> header = Letter::addHeader; format("kaituozhe", header.andThen(Letter::addFooter));

   注:如上代码会先对`kaituozhe`执行addHeader方法 然后对结果执行 addFooter方法

public static String format(String text, Function<String, String> function) { return function.apply(text);}public class Letter { public static String addHeader(String text) { return "--- Header --- \n" + text; } public static String addFooter(String text) { return text + "\n--- Footer ---"; }}
  • compose : 先把参数作用于第二个函数,其结果作用于第一个函数

    注 : 通过debug会发现下面案例会先执行addHeader方法

 如:Function<String, String> header = Letter::addHeader; format("kaituozhe", header.compose(Letter::addFooter));
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { return (V v) -> apply(before.apply(v));}
  • identity : 传入一个T返回一个T  原样返回 

案例 : 如下两个案例效果是一样的

传入一个函数式接口 :

orangeList.stream() .collect(Collectors.toMap(Orange::getWeight, e -> e));

使用Function接口中的静态方法 : 

orangeList.stream() .collect(Collectors.toMap(Orange::getWeightFunction.identity()));
static <T> Function<T, T> identity() { return t -> t;}


Consumer<T> -> void accept(T t) : 消费型接口 传入类型T

List<String> strList = Arrays.asList("a", "b", "c");Lambda : strList.forEach(str -> System.out.println(str));方法应用 : strList.forEach(System.out::println);default void forEach(Consumer<? super T> action) { for (T t : this) { action.accept(t); }}

进阶方法

  • andThen : 先把参数作用于函数一进行执行,再把同样的参数作用于函数二进行执行

  如 : 如下代码会先执行保存数据库函数 再 执行保存Redis函数 

     如果保存数据库失败  就不会执行到 保存Redis

Consumer<String> consumer = (obj) -> {     System.out.println(obj + " : 保存数据库");     throw new RuntimeException("");};consumer("订单", consumer.andThen((i) -> System.out.println(" : 保存Redis")));
public static <T> void consumer(T t, Consumer<T> consumer) { consumer.accept(t);}


Predicate<T> -> boolean test(T t) :用于判断 传入类型T 返回boolean


Lambda : isEmpty("", a -> a == null || a.equals(""))

方法引用 : isEmpty("", String::isEmpty) 

 参数二:在这次调用中表示需要传一个 入参为String类型返回为boolean类型的方法

public static <T> boolean isEmpty(T str, Predicate<T> predicate) { return predicate.test(str);}


进阶方法

  • and : 方法返回一个复合谓词,表示和另一个谓词的短路与关系 

    • 如:谓词1 &&(and) 谓词2

  • or : 方法返回一个复合谓词,表示和另一个谓词的短语或关系  

    • 如:谓词1 ||(or) 谓词2

  如 : 取红色或绿色的橘子  并且他们大于150克  下面两个案例结果是一样的

案例1 : 

orangeList.stream().filter(p.and(orange -> orange.getColor().equals("red")) .or(orange -> orange.getColor().equals("green")) .and(orange -> orange.getWeight() > 150)).collect(Collectors.toList());

案例2 : 

orangeList.stream().filter(orange -> (orange.getColor().equals("red") ||  orange.getColor().equals("green")) &&  orange.getWeight() > 150).collect(Collectors.toList());
  • negate : 取反

    如 : 取不是红色的橘子

orangeList.stream() .filter(p.and(orange -> orange.getColor().equals("red")).negate()) .collect(Collectors.toList());
  • Predicate.isEqual : 把值跟函数中的值做比较,返回所有相匹配的
    如: 返回所有红色

orangeList.stream().map(Orange::getColor) .filter(Predicate.isEqual("red")) .collect(Collectors.toList());

Supplier<T> -> T get() : 创建型 : 没有传入  返回类型T

Lambda : createBean(() -> new User());方法引用 : createBean(User::new);public static <T> T createBean(Supplier<T> supplier) { return supplier.get();}


关注我更好的学习技术

看完记得点赞