常用的函数式接口

常用函数式接口

  • 仅含有一个抽象方法的接口(不是只有一个方法)
  • 该接口常与Lambda表达式相联系
  • Lambda表达式延迟加载,可避免性能浪费

Supplier -生产型接口


  • java.util.function.Supplier 接口仅包含一个无参的方法:T get(),用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。
  • Supplier<>接口被称为生产型接口,指定接口的泛型是什么类型,那么接口的get方法就会生产什么类型的数据,有返回值。
package cn.learn;

import java.util.function.Supplier;

public class function {
    //定义一个方法,方法参数传递Supplier<>接口,泛型执行String.get方法就会返回一个String
    public static String getString(Supplier<String> stringSupplier){
        return stringSupplier.get();
    }

    public static void main(String[] args) {
        //调用getString方法,方法的参数是一个函数式表达接口,所以传递lambda表达式
        String str = getString(() ->{
           //生产一个字符串,并返回
           return "aaa";
        });

        System.out.println(str);

        //优化Lambda表达式
        str = getString(() -> "aaa");

        System.out.println(str);

    }
}

练习:求数组元素最大值


package cn.learn;

import java.util.function.Supplier;

public class function {
    public static Integer getMax(Supplier<Integer> stringSupplier){
        return stringSupplier.get();
    }

    public static void main(String[] args) {
        //定义一个数组
        int[] arr = new int[]{3,55,66,77,88,-5};

        //调用getMax方法,使用Lambda表达式简写
        int integermax = getMax(() ->{
           //获取数组最大值并返回
           int max = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if (max < arr[i]){
                    max = arr[i];
                }
            }
            return max;
        });

        /******
        //调用getMax方法
        getMax(new Supplier<Integer>() {
            @Override
            public Integer get() {
                //获取数组最大值并返回
                int max = arr[0];
                for (int i = 1; i < arr.length; i++) {
                    if (max < arr[i]) {
                        max = arr[i];
                    }
                }
                return max;
            }
        });
        *******/

        System.out.println(integermax);
    }
}

Consumer -消费型接口


  • java.util.function.Consumer接口正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定
  • Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据,无返回值
package cn.learn;

import java.util.function.Consumer;

public class function {
    //accept方法接受的数据可以输出、计算等
    public static void print(Integer year,Consumer<Integer> age){
        age.accept(year);
    }

    public static void main(String[] args) {

        //消费方式:直接输出
        print(2018,(year) -> System.out.println("你的出生年是"+year));

        //消费方式:反转字符串
        print(2018,(year) -> {
            String string = year.toString();
            String re = new StringBuilder(string).reverse().toString();
            System.out.println(re);
        });
    }
}
  • Consumer方法中的默认方法——andThen
  • 如果一个方法的参数和返回值全部是Consumer类型,那么就可以实现:消费数据的时候,首先做一个操作,然后在做一个操作,实现组合,而这个方法就是Consumer接口中的default方法
  • JDK源码
   default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }

注:java.util.Object的requireNonNull静态方法将会在参数为null时主动抛出NullPointerException异常,这就省去编写if语句和抛出空指针异常的麻烦。

  • 若想实现组合效果,需要两个Lambda表达式即可,而andThen的语义正是“一步接一步”操作,例如两个步骤组合的情况:

    • Consumer con1;
      Consumer con2;
      String str = "hello";
      con1.accept(str);
      con2.accept(str);

package cn.learn;

import java.util.function.Consumer;

public class function {
    //把两个Consumer接口组合到一起,再对数据进行消费
    public static void method(String str,Consumer<String> con1,Consumer<String> con2){

        //使用原始方式
        con1.accept(str);
        con2.accept(str);

    }

    public static void main(String[] args) {

        //原始使用方式,调用method方法,需要传递两个Lambda表达式
        method("Hello",(str) -> {
            //消费方式:转为大写
            System.out.println(str.toUpperCase());
        },(str) ->{
            //消费方式:转为小写
            System.out.println(str.toLowerCase());
        });

    }
}
  • 连接两个接口再进行消费(谁在前,谁先消费),可以改为
    con1.andThen(con2).accept(str);
package cn.learn;

import java.util.function.Consumer;

public class function {
    //andThen需要两个Consumer接口,可以把两个Consumer接口组合到一起,再对数据进行消费
    public static void method(String str,Consumer<String> con1,Consumer<String> con2){

        //先使用con1消费数据,再使用con2
        con1.andThen(con2).accept(str);

    }

    public static void main(String[] args) {

        //原始使用方式,调用method方法,需要传递两个Lambda表达式
        method("Hello",(str) -> {
            //消费方式:转为大写
            System.out.println(str.toUpperCase());
        },(str) ->{
            //消费方式:转为小写
            System.out.println(str.toLowerCase());
        });

    }
}

练习:格式化打印信息


package cn.learn;

import java.util.function.Consumer;

public class function {
    //使用两个Consumer来消费字符串,泛型为字符数组
    public static void method(String[] str,Consumer<String[]> con1,Consumer<String[]> con2){

        //先使用con1消费数据,再使用con2
        con1.andThen(con2).accept(str);

    }

    public static void main(String[] args) {

        //定义一个字符串数组
        String[] person ={"小王,男","大王,女"};

        //原始使用方式,调用method方法,需要传递两个Lambda表达式
        method(person,(str) -> {
            //消费方式:取人名
            for (String name:str) {
                //取第一个元素
                System.out.println(name.split(",")[0]);
            }
        },(str) ->{
            //消费方式:取性别
            for (String name:str) {
                //取第一个元素
                System.out.println(name.split(",")[1]);
            }
        });
    }
}

结果:
小王
大王

  • 另一种写法

package cn.learn;

import java.util.function.Consumer;

public class function {
    //使用两个Consumer来消费字符串,泛型为字符数组
    public static void method(String[] str,Consumer<String> con1,Consumer<String> con2){
        //将遍历写在此处,预防重复造轮子
        for (String message:str) {
            //先使用con1消费数据,再使用con2
            con1.andThen(con2).accept(message);
        }

    }

    public static void main(String[] args) {

        //定义一个字符串数组
        String[] person ={"小王,男","大王,女"};

        //原始使用方式,调用method方法,需要传递两个Lambda表达式
        method(person,(message) -> {
            //消费方式:取人名
                System.out.println(message.split(",")[0]);
        },(message) ->{
            //消费方式:取性别
                System.out.println(message.split(",")[1]);
        });
    }
}

结果:
小王

大王

Predicate -判断接口


  • 有时候我们需要对某种数据类型的数据进行判断,从而得到一个boolean值的结果,这时可以使用java.util.function.predicate接口
  • Predicate接口中含有一个抽象方法:boolean test(T t)。用于条件判断的场景,返回值为布尔值

```java
package cn.learn;

import java.util.function.Predicate;

public class function {
//
public static boolean checkMethod(String str, Predicate pre){
return pre.test(str);
}

public static void main(String[] args) {

    String str = "hello"; 

    //对字符串进行校验
    boolean check = checkMethod(str,(String str01) ->{
       return str01.length()>5;
    });

    boolean check1 = checkMethod(str,str01 -> str01.length()>3);

    System.out.println(check);
    System.out.println(check1);
}

}

  • 默认方法:and -可以判断多个判断条件和“&&”差不多
package cn.learn;

import java.util.function.Predicate;

public class function {
    //
    public static boolean checkMethod(String str, Predicate<String> pre1, Predicate<String> pre2){
        //等价于return pre1.test(str) && pre2.test(str);
        return pre1.and(pre2).test(str);
    }

    public static void main(String[] args) {

        String str = "hello";

        //对字符串进行校验
        boolean check = checkMethod(str,(String str01) ->{
           return str01.length()>3;
        },(str01) ->{
            return str01.contains("1");
        });

        System.out.println(check);
    }
}

false

  • 默认方法:or -可以判断多个判断条件和“||”差不多
package cn.learn;

import java.util.function.Predicate;

public class function {
    //
    public static boolean checkMethod(String str, Predicate<String> pre1, Predicate<String> pre2){
        //等价于return pre1.test(str) || pre2.test(str);
        return pre1.or(pre2).test(str);
    }

    public static void main(String[] args) {

        String str = "hello";

        //对字符串进行校验
        boolean check = checkMethod(str,(String str01) ->{
           return str01.length()>3;
        },(str01) ->{
            return str01.contains("1");
        });

        System.out.println(check);
    }
}

true

  • 默认方法:negate -可以判断多个判断条件和“!”差不多

package cn.learn;

import java.util.function.Predicate;

public class function {
    //
    public static boolean checkMethod(String str, Predicate<String> pre1){
        //等价于return !pre1.test(str);
        return pre1.negate().test(str);
    }

    public static void main(String[] args) {

        String str = "hello";

        //对字符串进行校验
        boolean check = checkMethod(str,(String str01) ->{
           return str01.length()>3;
        });

        System.out.println(check);
    }
}

false

练习:集合信息筛选


  • 将名字为2个字且为女生的字符串选到集合中,注意字符串判断需要用equals方法
package cn.learn;

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

public class function {

    public static ArrayList<String> filter(String[] str, Predicate<String> pre1, Predicate<String> pre2) {

        //放外边,里边会重复申请
        ArrayList<String> correct = new ArrayList<>();
        //遍历数组
        for (String message : str) {
            boolean ifCorr = pre1.and(pre2).test(message);
            //满足条件的放入集合
            if (ifCorr) {
                correct.add(message);
            }
        }
        return correct;

    }

    public static void main(String[] args) {

        String[] str = {"小王,女", "大王,男", "小白,男", "王小白,女"};

        //对字符串进行筛选,并返回需要的集合
        ArrayList<String> list = filter(str, (String str01) -> {
            return str01.split(",")[0].length() == 2;
        }, (str01) -> str01.split(",")[1].equals("女") );

        System.out.println(list);
    }
}

[小王,女]

Function -数据类型转换接口


  • java.util.function.Function<T,R>接口用来根据一个数据类型得到另一个数据类型,前者称为前置条件,后者称为后置条件。
  • 抽象方法:apply,R apply,根据类型T的参数获取R型的结果,返回的是另一个类型的值。
package cn.learn;

import java.util.function.Function;

public class function {

    public static Integer convert(String str, Function<String,Integer> function){
        //返回一个Integer类型
        return function.apply(str);
    }

    public static void main(String[] args) {
        String str = "2018";
        //调用convert方法转换类型,并用Lambda表达式重写apply方法
        Integer strInt = convert(str,(String str01) ->{
           return  Integer.parseInt(str01);
        });

        System.out.println(strInt);
    }
}
  • 默认方法:andThen,用来进行组合操作
  • 需求:把字符串转换为Integer类型,把结果进行运算,
    再把整型转换回去
package cn.learn;

import java.util.function.Function;

public class function {

    public static String convert(String str, Function<String,Integer> fun1,Function<Integer,String> fun2){
        //返回一个String类型
        return fun1.andThen(fun2).apply(str);
    }

    public static void main(String[] args) {
        String str = "2018";
        //调用convert方法转换类型,取出字符串对应的值并进行运算,再转换为String
        str = convert(str,str01 ->Integer.parseInt(str01)+10,int01 -> int01.toString());
        System.out.println(str);
    }
}

2028

原文地址:https://www.cnblogs.com/huxiaobai/p/11621436.html

时间: 2024-11-09 07:59:22

常用的函数式接口的相关文章

常用函数式接口

常用函数式接口 JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function 包中被提供. 下面是简单的几个接口及使用示例. Supplier接口 java.util.function.Supplier<T> 接口仅包含一个无参的方法: T get() .用来获取一个泛型参数指定类型的对 象数据.由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要"对外提供"一个符合泛型类型的对象 数据 /* 常用的函数式接

Java 常用函数式接口 —— Consumer接口

JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function 包中被提供. 下面是最简单的Consumer接口及使用示例. Consumer接口概述 @FunctionalInterface public interface Consumer<T> { /** * 对给定参数执行消费操作. * * @param t 输入参数 */ void accept(T t); default Consumer<T> andThen(Con

Java 常用函数式接口 —— Supplier接口

JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function 包中被提供. 下面是最简单的Supplier接口及使用示例. Supplier接口概述 // Supplier接口源码 @FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); } java.util.function.Supp

乐字节-Java8核心特性实战之函数式接口

什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口. java8引入@FunctionalInterface 注解声明该接口是一个函数式接口. 语法 抽象方法有且仅有一个 接口使用@FunctionalInterface 注解进行标注 接口中可以存在默认方法和静态方法实现 如下形式: /** * 定义函数式

Java 函数式接口

目录 Java 函数式接口 1. 函数式接口 1.1 概念 1.2 格式 1.3 函数式接口的使用 2. 函数式编程 2.1 Lambda的延迟执行 2.2 使用Lambda作为方法的参数&返回值 3. 常用的函数式接口 3.1 Supplier<T>接口 3.2 Consumer<T>接口 3.3 Predicate<T>接口 3.4 Function<T, R>接口 Java 函数式接口 1. 函数式接口 1.1 概念 函数式接口:有且只有一个抽

Java常用函数式接口--Consumer接口andThen()方法使用案例(二)

Java常用函数式接口--Consumer接口使用案例 原文地址:https://www.cnblogs.com/niwotaxuexiba/p/10852243.html

常用函数式接口与Stream API简单讲解

常用函数式接口与Stream API简单讲解 Stream简直不要太好使啊!!! 常用函数式接口 Supplier<T>,主要方法:T get(),这是一个生产者,可以提供一个T对象. Consumer<T>,主要方法:void accept(T),这是一个消费者,默认方法:andthen(),稍后执行. Predicate<T>,主要方法:boolean test(T t),这是一个判断者,默认方法:and():且,or():或,negate():非. Functio

阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第1节 常用函数接口_1_函数式接口的概念&amp;函数式接口的定义

没有参数,没有返回值的抽象方法 一个接口中是可以有多个抽象方法的,如果在这里在定义一个method2.这样里面有两个抽象方法就不是函数式接口了. 确保接口中就一个抽象方法的方式 定义接口的实现类,重写里面的抽象方法 重写了以后,方法上加了注解叫做@Override 复制上面的method2到下面改成叫做method3就报错了.错误提示.method3不是一个可重写的方法.这就是注解的作用. 这个时候就 编译失败了,因为里面有两个抽象方法 只保留一个抽象方法,就不会报错了. 一个抽象方法都没有也会

Java8 Lambda - Functioanl Interface 函数式接口

在java 8 里面新增了functional interface 这个概念.并且添加了新的annotation @FunctionalInterfaceI 1 什么是functional interface 函数式接口了? functional interface : functional interface only have 1 abstract method. 这就是函数接口的定义.简单明白,函数接口其实就是一个抽象方法的接口(interface). 2 函数式接口的类型 这里我只介绍基