Java函数式编程

89 阅读3分钟

函数式接口

介绍

  1. 只有一个抽象方法的接口则称为函数式接口
  2. 声明函数时不做具体实现
  3. 调用时决定实现方式

函数式编程可以把函数当成一个入参,很像策略模式,不同场景,传入不同策略的具体实现。

四大函数式接口

先简单说明一下,当入参是函数式接口时,可以传入lamda表达式。 lamda表达式的语法: () -> {} 箭头左边入参,右边为具体实现。

Consumer,消费型接口

介绍:接收一个入参对其操作,无返回值。因为很像消费者,所以称为消费型接口。

	@FunctionalInterface
    public interface Consumer<T> {
        void accept(T t);
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    }

实操案例 先定义一个带消费者接口的函数(方法)

	/**
     * 我们要消费一个double类型的对象:
	 * 第一个入参定义消费对象。
     * 第二个则是我们要使用的消费者接口,至于怎么消费这里不做实现,具体实现在调入时传入。
     * @param s
     * @param fun
     * @return
     */
    public static void happy(double money,Consumer<Double> con){
        con.accept(money);
    }

调用刚刚定义的函数

public static void main(String[] args) {
    //调用时对消费数据做具体实现
    happy(2000,m -> System.out.println("在环球影城happy,花费了:"+m+"元"));
}

//打印结果:在环球影城happy,花费了:2000.0元

Supplier,供给型接口

介绍:接口方法无入参,带返回值,至于返回什么,由调用时传入。

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

实操案例 先定义一个带供给者接口的函数(方法)

	/**
     * 我们想产生指定个数的整数,并放入集合
     * 第一个入参,是根据需求来控制想产生的整数的个数。
	 * 第二个入参,供给型接口,list添加的元素,就是此接口产生的,至于元素具体是什么,由调用时实现。
     * @param supplier
     * @return
     */
    public static ArrayList<Integer> getList(int num,Supplier<Integer> supplier){
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            list.add(supplier.get());
        }
        return list;
    }

调用刚刚定义的函数

public static void main(String[] args) {
    //1.向集合中添加5个元素 
    //2.至于添加的元素是什么,我们的实现为添加100内的随机数
    System.out.println(getList(5,()->new Random().nextInt(100) + 1));
}

//打印结果:[30, 1, 81, 45, 29]

Function,函数型接口

介绍:接口方法由入参,有返回值。

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

实操案例 先定义一个带函数式接口

	/**
     * 用于处理字符串
     * 第一个入参为我们要处理的字符串
     * 第二个入参为函数式接口,至于如何处理入参,返回怎样的值,由调用式实现
     * @param s
     * @param fun
     * @return
     */
    public static String strHandler(String s, Function<String,String> fun){
        return fun.apply(s);
    }

调用刚刚定义的函数

public static void main(String[] args) {
    //第一个入参是要处理的字符串,函数式接口的具体实现为截取入参字符串的前六位
    System.out.println(strHandler("这是一个长度为13的字符串", s -> s.substring(0,6)));
}

//打印结果:这是一个长度

Predicate,断言型接口

介绍:传入一个入参返回一个布尔值。

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

实操案例 先定义一个带函数式接口

	/**
     * 将满足条件的字符串添加到新的集合中
	 * 第一个入参为要处理的集合
     * 第二个入参为断言型接口,对入参进行判断,返回布尔值,至于怎么判断由调用者实现
     */
    public static List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> stringList = new ArrayList<>();
        for (String str : list){
            //满足断言实现则加入
            if(pre.test(str)) {
                stringList.add(str);
            }
        }
        return stringList;
    }

调用刚刚定义的函数

    public static void main(String[] args) {
        //待处理的集合
        List<String> list = Arrays.asList("Hello","predicate","Lambda","www","ok");
        //第一个入参,传入待处理的集合,第二个入参实现断言接口,长度大于3的字符串返回true
        List<String> stringList = filterStr(list,s->s.length()>3);
        System.out.println(stringList);
    }

	//打印结果:[Hello, predicate, Lambda]