函数式接口的学习

函数式接口

如果说一个接口内有且只有一个方法,而且该方法是一个缺省属
性为public abstract方法,该接口可以称之为是一个函数式接口。

Comparator Runnable

@FunctionalInterface 使用,检查函数式接口格式问题。

要求当前接口中有且只有一个缺省属性为public abstract 的方法。

代码中使用函数式接口

	1. 让程序的目的性更强。

	2. 提供复用,普适性的价值。

	3. 节约资源。

函数式编程思想

Lambda延迟执行

日志记录是否保存存在等级限制

  package com.qfedu.b_lambda;
    
    /**
     * 日志等级记录操作
     *
     * @author Anonymous 2020/3/11 19:11
     */
    public class Demo1 {
        public static void main(String[] args) {
            /*
            这里存问题:
                MIDDLE,LOWER是没有必要进行字符串累加,存在资源浪费问题。
    
                字符串的累加过程,需要经过Level判断之后才可以执行,避免没有必要的性能浪费。
    
                这里就可以使用Lambda表达式执行的延迟性,在没有满足level情况下,不去做字符串累加
                过程。这里需要函数式接口
             */
            log(Level.MIDDLE, "异常位置XXX," + "异常问题XXX," + "异常时间XXX");
        }
    
        /**
         * 判断等级,是否需要记录当前日志信息
         *
         * @param level  枚举类型
         * @param logMsg 需要记录的日志信息
         */
        public static void log(Level level, String logMsg) {
            // 判断是否满Level.HIGH要求
            if (Level.HIGH == level) {
                System.err.println(logMsg);
            }
        }
    }
    

使用函数式接口提供日志信息功能

这里需要函数式接口,返回值类型是String类型

package com.qfedu.b_lambda;

/**
 * 返回值为String类型方法的函数式接口
 *
 * @author Anonymous 2020/3/11 19:45
 */
@FunctionalInterface
public interface LogMessage {
    String returnLogMessage();
}




package com.qfedu.b_lambda;

/**
 * 使用函数式接口完成Log日志记录问题
 *
 * @author Anonymous 2020/3/11 19:47
 */
public class Demo2 {
    public static void main(String[] args) {
        String msg1 = "异常位置XXX";
        String msg2 = "异常问题XXX";
        String msg3 = "异常时间XXX";

        log(Level.HIGH, () -> {
            System.out.println("Lambda表达式执行!!!");
            return msg1 + msg2 + msg3;
        });
    }

    /**
     * 根据日志等级Level来确定是否需要记录日志
     *
     * @param level 枚举类型,数据为 HIGH MIDDLE LOWER
     * @param lm LogMessage函数式接口做方法的参数
     */
    public static void log(Level level, LogMessage lm) {
        if (Level.HIGH == level) {
            // 通过函数式接口获取调用对应的returnLogMessage()方法
            System.err.println(lm.returnLogMessage());
        }
    }
}

Lambda作为方法参数和返回值

匿名内部类来完成对应当前Runnable接口实现类对象使用,作为Thread构造方法参数。

 new Thread(new Runnable() {
            @Override
            //执行目标
            public void run() {
                System.out.println("线程代码");
            }
        }).start();

Lambda表达式直接作为方法的参数。

 Thread thread = new Thread(() -> {

            System.out.println("线程执行的时间");

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程执行");
        }
        , "线程");

        thread.start();

Java中提供的比较接口Comparator

利用一些返回值作为方法中操作的条件

public interface Comparator<T> {

	int compare(T o1, T o2);

}

package com.qfedu.b_lambda;

import java.util.Arrays;
import java.util.Comparator;

/**
 * Lambda表示完成函数式接口,利用返回值作为其他操作所需的数据
 *
 * @author Anonymous 2020/3/11 20:11
 */
public class Demo4 {
    public static void main(String[] args) {
        /*
        排序默认字典顺序
         */
        String[] arr = {"3eeeeeeee", "2a","dddd",  "1bb", "ccccccc", "3fffff"};

        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));

        System.out.println("-------------------");

        // 利用函数式接口完成的方法,利用方法的返回值作为当前sort方法运行
        // 所需参数,该参数用于比较规则约束
        Arrays.sort(arr, stringComparator());
        System.out.println(Arrays.toString(arr));

        System.out.println("--------------------");

        Arrays.sort(arr, (a, b) -> a.length() - b.length());
        System.out.println(Arrays.toString(arr));
        
        Arrays.sort(arr, Comparator.comparingInt(String::length));
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 按照字符串长度排序,返回值类型是Comparator<String>接口
     * 这里需要完成Comparator接口中的compare方法
     *
     * @return 已经完成方法体的Comparator接口,并且数据类型是String类型
     */
    public static Comparator<String> stringComparator() {
        return (a, b) -> a.length() - b.length();
    }
}

Java中提供的常用函数式接口

Supplier 生产者, 返回一个指定类型的数据。

java.util.function.Supplier

有且只有一个方法

T get(); 不需要参数,返回指定T类型数据

package com.qfedu.c_supplier;

import com.qfedu.b_lambda.Level;

import java.util.function.Supplier;

/**
 * Supplier演示
 *
 * @author Anonymous 2020/3/11 20:24
 */
public class Demo1 {
    public static void main(String[] args) {
        String msg1 = "异常位置XXX";
        String msg2 = "异常问题XXX";
        String msg3 = "异常时间XXX";

        log(Level.HIGH, () -> msg1 + msg2 + msg3);
    }

    /**
     * 根据日志等级Level来确定是否需要记录日志
     *
     * @param level Level枚举类型,有三个数据 HIGH MIDDLE LOWER
     * @param supplier Supplier函数式接口,利用T get() 完成提供数据操作
     */
    public static void log(Level level, Supplier<String> supplier) {
        /*
        利用get方法,提供对应的返回指定String类型数据
         */
        if (Level.HIGH == level) {
            // 通过函数式接口获取调用对应的returnLogMessage()方法
            System.err.println(supplier.get());
        }
    }
}


Consumer<T> 消费者, 消耗一个指定类型的数据。

	Consumer<T>

	操作使用的方式是  void accept(T t);

	根据接口指定的数据类型接收对应数据,进行	

	处理和消费,对外没有任何的返回。

package com.qfedu.d_consumer;

import java.util.function.Consumer;

/**
 * Consumer处理数据
 *
 * @author Anonymous 2020/3/11 20:33
 */
public class Demo1 {
    public static void main(String[] args) {
        // 该方法需要的参数是一个String类型,同时使用Consumer接口处理数据
        // 因为Consumer接口是一个函数式接口,可以使用Lambda表达式
        testConsumer("你,我,他", (string) -> {
            String[] split = string.split(",");
            for (String s : split) {
                System.out.print(s);
            }
        });
    }

    /**
     * 给予一个String类型,通过Consumer函数式接口中的accept方法完成对应字符串处理
     *
     * @param string String类型字符串
     * @param consumer Consumer处理数据的函数式接口
     */
    public static void testConsumer(String string, Consumer<String> consumer) {
        consumer.accept(string);
    }
}

Predicate 判断调节,过滤使用。

Predicate一般用于调节判断,过滤数据的方法。

函数式接口中指定的方法

boolean test(T t);

处理T类型数据,返回boolean true / false

package com.qfedu.e_predicate;

import java.util.function.Predicate;

/**
 * Predicate<T>使用
 *
 * @author Anonymous 2020/3/11 20:42
 */
public class Demo1 {
    public static void main(String[] args) {

        // Predicate函数式接口,使用Lambda表达式作为方法的参数
        boolean b = testPredicate("中国加油!!!",
                (str) -> {
                    return str.contains("加油");
                });

        System.out.println(b);

        /*
        优化Lambda表达式,
         */
        testPredicate("中国加油!!!", str -> str.contains("加油"));
    }

    /**
     * 使用Predicate函数式接口利用boolean test(T t)对于当前数据进行判断
     *
     * @param str String类型字符串
     * @param pre 处理使用Predicate函数式接口
     * @return 判断接口是否满足要求,满足返回true,不满足返回false
     */
    public static boolean testPredicate(String str, Predicate<String> pre) {
        return pre.test(str);
    }
}

Function<T,R> 类型转换,根据你指定的类型T, 转

换成对应类型R。

使用R apply(T t) 转换指定类型T到R。

package com.qfedu.f_function;

import com.qfedu.c_supplier.Person;

import java.util.function.Function;

/**
 * Function<T, R> 函数式接口
 *      R apply(T)
 *
 * @author Anonymous 2020/3/11 20:51
 */
public class Demo1 {
    public static void main(String[] args) {
        // 数字转字符串
        String change = change(10, i -> i + "");
        System.out.println(change);

        // 利用函数式接口处理一个String类型,转换成对应的Person类型
        Person person1 = change("1,骚磊,16", str -> {
            //解析字符串
            String[] split = str.split(",");
            Person person = new Person();

            person.setId(Integer.parseInt(split[0]));
            person.setName(split[1]);
            person.setAge(Integer.parseInt(split[2]));

            return person;
        });

        System.out.println(person1);
    }

    /**
     * 目标数据从Integer类型转换到指定数据String类型
     *
     * @param i 目标数据Integer类型
     * @param fun 转换使用的Function函数式接口
     * @return 返回值的是String类型
     */
    public static String change(Integer i, Function<Integer, String> fun) {
        return fun.apply(i);
    }

    public static Person change(String str, Function<String, Person> fun) {
        return fun.apply(str);
    }
}
发布了16 篇原创文章 · 获赞 4 · 访问量 753

猜你喜欢

转载自blog.csdn.net/sjn2212297386/article/details/104805625
今日推荐