JDK8新特性笔记(四):函数式编程

JDK8新特性笔记(四):函数式编程

  • Java8 内置的四大核心函数式接口
    Consumer : 消费型接口:有入参,无返回值
    void accept(T t);
  • Supplier : 供给型接口:无入参,有返回值
    T get();
  • Function<T, R> : 函数型接口:有入参,有返回值
    R apply(T t);
  • Predicate : 断言型接口:有入参,有返回值,返回值类型确定是boolean
    boolean test(T t);

1.Function接口的使用

先写一个function接口的实现类,重写apply方法

public class FunctionObj implements Function {

    @Override
    public Object apply(Object o) {
        return o+"经过apply()处理拼接上了";
    }
}

再写一个调用这个实现方法的类

public static void test(String input,FunctionObj func){
    // 加了一个转大写的功能
    String upperCase = input.toUpperCase();
    System.out.println(func.apply(upperCase));
}

使用:

public static void main(String[] args) {
    // 直接调用自己写的实现方法
    test("aBc",new FunctionObj());

    // lambda方式重写apply方法,再调用
    Function<Integer,Integer> func = p->p*100;
    System.out.println(func.apply(3));
}

运行结果:
ABC经过apply()处理拼接上了
300

2.BiFunction :Function只能接受一个参数,如果要传递两个参数,则用BiFunction

截取部分BiFunction源码及注释,传入两个参数返回一个结果,使用接口去自定义功能实现

/**
 * Represents a function that accepts two arguments and produces a result.
 * This is the two-arity specialization of {@link Function}.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #apply(Object, Object)}.
 *
 * @param <T> the type of the first argument to the function
 * @param <U> the type of the second argument to the function
 * @param <R> the type of the result of the function
 *
 * @see Function
 * @since 1.8
 */
@FunctionalInterface
public interface BiFunction<T, U, R> {

    /**
     * Applies this function to the given arguments.
     *
     * @param t the first function argument
     * @param u the second function argument
     * @return the function result
     */
    R apply(T t, U u);

使用例子:

public static void main(String[] args) {

    System.out.println(CaculateFunction(6,3,(a,b)->a+b));
    System.out.println(CaculateFunction(6,3,(a,b)->a-b));
    System.out.println(CaculateFunction(6,3,(a,b)->a*b));
    System.out.println(CaculateFunction(6,3,(a,b)->a/b));

}

// 实现类 应用入口
public static Integer CaculateFunction(Integer numA, Integer numB, BiFunction<Integer,Integer,Integer> biFunction ){
    return biFunction.apply(numA,numB);
}

运行结果:
9
3
18
2

3.Consumer:消费型接口 ;有入参 无返回值

截取部分Consumer源码及注释

/**
 * Represents an operation that accepts a single input argument and returns no
 * result. Unlike most other functional interfaces, {@code Consumer} is expected
 * to operate via side-effects.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object)}.
 *
 * @param <T> the type of the input to the operation
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

用途: 因为没有返回值,常用于打印、发送短信、遍历等消费动作

使用例子:

public static void main(String[] args) {
    sendMsg("发送信息测试",obj->{
        System.out.println(obj);
        System.out.println("消息发送完成");
    });
}

    public static void sendMsg (String msg, Consumer<String> consumer){
        consumer.accept(msg);
    }

运行结果:
发送信息测试
消息发送完成

遍历例子:

List<String> stringList = Arrays.asList("aaa", "bbb", "ccc");
stringList.forEach(obj->{
    System.out.println(obj);
});

运行结果:
aaa
bbb
ccc

4.Supplier :供给型接口 ; 无入参,有返回值

源码及注释

/**
 * Represents a supplier of results.
 *
 * <p>There is no requirement that a new or distinct result be returned each
 * time the supplier is invoked.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #get()}.
 *
 * @param <T> the type of results supplied by this supplier
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

用途:泛型一定跟方法的返回值类型是一种类型,如果需要获得一个数据,并且不需要传入参数,可以使用Supplier接口,例如 无参的工厂方法,即工厂设计模式创建对象,简单来说就是 提供者

写一个新建默认对象的例子:

public class SupplierDemo01 {

    public static void main(String[] args) {
        // 调用创建默认对象的方法去创建对象
        Person person = newPerson();
        System.out.println(person.getName());
    }

    /**
     * 创建一个创建默认对象的方法
     * @return
     */
    public static Person newPerson(){
        Supplier<Person> personSupplier = ()->{
            Person person = new Person();
            person.setName("god");
            person.setAge(99999);
            return person;
        };
        return personSupplier.get();
    }


}

/**
 * 创建一个Person类
 */
class Person {

    String name;

    int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

5.Predicate : 断言型接口:有入参,有返回值,返回值类型确定是boolean

部分源码及注释

/**
 * Represents a predicate (boolean-valued function) of one argument.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #test(Object)}.
 *
 * @param <T> the type of the input to the predicate
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);

用途: 接收一个参数,用于判断是否满足一定的条件,过滤数据

**例子:**做一个过滤字符串数组中所有非a开头的字符串,只留下以a开头的字符串放到数组中返回

public class PredicateDemo01 {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("abc", "bcd", "cde", "def", "ace");
        System.out.println(strings);
        // 第二个参数把过滤策略传入
        List<String> results = startWithAFilter(strings, obj -> obj.startsWith("a"));
        System.out.println(results);

    }

    /**
     * 做一个过滤器
     * @param list
     * @param predicate
     * @return
     */
    public static List<String> startWithAFilter (List<String> list , Predicate<String> predicate){
        ArrayList<String> result = new ArrayList<>();
        for (String str : list){
            if (predicate.test(str)) {
                result.add(str);
            }
        }
        return result;
    }
}

6.方法引用与构造函数的引用

以前方法调用 对象.方法名 或者 类名.方法名

jdk8提供了一个 :: 双冒号

说明:方法引用是一种更更简洁易懂的lambda表达式,操作符是双冒号::,用来直接访问类或者实例已经存在的方法或构造方法

通过方法引用,可以将方法的引用赋值给一个变量

语法:左边是容器(可以是类名,实例名),中间是" :: ",右边是相应的方法名

静态方法,则是ClassName::methodName。如 Object ::equals

实例例方法,则是Instance::methodName

构造函数,则是 类名::new;

public class ConstructDemo01 {

    public static void main(String[] args) {

        // 用双冒号来构造 静态函数引用  字符串转integer
        Function<String,Integer> fun = Integer::parseInt;
        Integer value = fun.apply("2048");
        System.out.println(value);

        // 用双冒号来构造 非静态函数引用  字符串剪切
        String str1 = "123测试字符串";
        Function<Integer,String> fun2 = str1::substring;
        String result1 = fun2.apply(2);
        System.out.println(result1);

        // 构造函数引用多个参数 这个每次调用apply就相当于new了一个User对象,如果要做一个User的list方便创建插入
        BiFunction<String,Integer,User> biFunction1 = User::new;
        User user1 = biFunction1.apply("kakaka1", 15);
        System.out.println(user1);

        // 构造函数引用单个参数
        Function<String,User> addFunction = User::new;
        User user2 = addFunction.apply("zouzouzou");
        System.out.println(user2);

        // 函数引用也是一种函数式接口,可以将函数引用作为方法的参数
        sayHello("大家好,我是sayHello",String::toUpperCase);
    }

    private static void sayHello(String param , Function<String,String> function){
        String result = function.apply(param);
        System.out.println(result);
    }
}
class User{
    private String name;

    private Integer age;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值