学习笔记之函数式接口

函数式接口

概述

  1. 函数式接口:有且仅有一个抽象方法的接口
    java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以适用于Lambda使用的接口,只有确保接口中有且仅有一个抽象方法,java中的Lambda才能顺利进行推导
  2. 检测一个接口是否是函数式接口
    • @FunctionalInterface
    • 放在接口定义的上方:如果接口是函数式接口,编译通过;反之,编译失败

定义函数式接口时,@FunctionalInterface可选,就算不写,只要保证满足函数式接口定义条件,也照样是函数式接口(建议加上该注解)。

函数式接口作为方法的参数

需求:

  • 定义一个(Demo),在类中提供两个方法
    1. startThread(Runnable r)方法参数Runnable是一个函数式接口
    2. 主方法,调用startThread方法
public class Demo {
    public static void main(String[] args) {
        startThread(() -> System.out.println(Thread.currentThread().getName()+"线程启动了"));
    }
    private static void startThread(Runnable r){
        new Thread(r).start();
    }
}

如果方法的参数是一个函数式接口,可以使用Lambda表达式作为参数传递

函数式接口作为接口的返回值

需求:

  • 定义一个类(Demo),在类中提供两个方法
    1. CompartorgetCompartor()方法的返回值式Commpartor是一个函数式接口
    2. 主方法调用getCommparator方法
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Demo {
    public static void main(String[] args) {
        ArrayList<String> a = new ArrayList<>();
        a.add("cc");
        a.add("aaaaa");
        a.add("bbb");
        Collections.sort(a,getCommparator());
        System.out.println(a);
    }
    private static Comparator<String> getCommparator(){
        //方法1
//        Comparator<String> c = new Comparator<String>() {
//            @Override
//            public int compare(String s, String t1) {
//                return s.length() - t1.length();
//            }
//        };
//        return c;

        //方法2
//        return new Comparator<String>() {
//            @Override
//            public int compare(String s, String t1) {
//                return s.length() - t1.length();
//            }
//        }

        //方法3
        return ( s1, s2) -> s1.length() -s2.length();
    }
}

如果方法的返回值式一个函数式接口,我们可以使用Lambda表达式结果返回

常用的函数是接口

java 8在java.util.function包下预定义了大量的函数式接口
如:

  1. Supplier接口
  2. Consumer接口
  3. Predicate接口
  4. Function接口
    等等
Supplier
  • Supplier:包含一个无参的方法
    • T get():获得结果
    • 该方法不需要参数,它会按照某种实现逻辑(由Lambda表达式实现)返回一个数据
    • Supplier接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据供我们使用
import java.util.function.Supplier;

public class Demo {
    public static void main(String[] args) {
        String s = getString(() -> "Hello,World");
        System.out.println(s);

        Integer i = getIneger(() -> 5);
        System.out.println(i);
    }

    private static int getIneger(Supplier<Integer> s) {
        return s.get();
    }

    private static String getString(Supplier<String> s) {
        return s.get();
    }
}

Supplier练习
  • 定义一个类(SupplierTest),在类中提供两个方法
    1. int getMax(Supplier s)用于返回一个int数组中的最大值
    2. 主方法调用getMax方法
import java.util.Arrays;
import java.util.function.Supplier;

public class SupplierTest {
    public static void main(String[] args) {
        int[] i = {1, 2, 3, 52, 68, 45};
        int IntegerMax = getMax(() -> {
                    Arrays.sort(i);
                    return i[i.length - 1];
                }
        );
        System.out.println(IntegerMax);
    }

    private static int getMax(Supplier<Integer> s) {
        return s.get();
    }
}

Consumer
  • Consumer:包含两个方法
    • void accept(T t):对给定的参数执行此操作
    • default Consumer andThe(Consumer after):返回一个组合的Consumer,一次执行此操作,然后执行after操作
    • Consumer接口也被称为消费型接口,它消费的数据的类型由泛型指定
import java.util.function.Consumer;

public class ConsumerDemo {
    public static void main(String[] args) {
        //Lambda表达式
        operatorString("Hello,World",s-> System.out.println(s));
        //方法引用
        operatorString("Hello,World",System.out::println);

    }
    private static void operatorString(String n, Consumer<String> c){
        c.accept(n);
    }
}
Consumer练习
  • String [] strArray = {"张三,18","李四,20","王五,19"}
  • 字符串数组中有多条信息,请按照格式:"姓名:XX,年龄:XX"的格式将信息打印出来
  • 需求:
    • 把打印姓名的动作作为一个Consumer接口的Lambda实例
    • 把打印年龄的动作作为第二个Consumer接口Lambda实例
    • 将两个Consumer接口按照顺序组合到一起
import java.util.function.Consumer;

public class ConsumerTest {
    public static void main(String[] args) {
        String [] strArray = {"张三,18","李四,20","王五,19"};
//        operatorConsumer(strArray,s -> {
//            String name = s.split(",")[0];
//            System.out.print("姓名:"+name);
//        },s -> {
//        int age = Integer.parseInt(s.split(",")[1]);
//            System.out.println(",年龄:"+age);
//        });
        operatorConsumer(strArray,
                s -> System.out.print("姓名:"+s.split(",")[0]),
                s -> System.out.println(",年龄:"+Integer.parseInt(s.split(",")[1])));
    }
    private static void operatorConsumer(String [] strArray, Consumer<String> c1, Consumer<String> c2){
        for (String i:strArray){
            c1.andThen(c2).accept(i);
        }
    }
}

Predicate接口
  • predicate:常用的四个方法
    1. boolean test(T t):对给定的参数进行判断(判断逻辑有Lambda表达式实现,返回一个布尔值)
    2. default Predicate negate():返回一个逻辑的否定,对应逻辑非
    3. default Predicate and(Predicate other):返回一个组合判断,对应短路与
    4. default Predicate or(Predicate other):返回一个组合判断,对应短路或
  • Predicate接口通常用于判断参数是否满足指定条件

test方法与negate方法:

import java.util.function.Predicate;
public class PredicateDemo {
    public static void main(String[] args) {
        boolean b1 = checkString("hello", s -> s.length() > 8);
        System.out.println(b1);

        boolean b2 = checkString("hello", s -> s.length() < 8);
    }

    //判断给定字符串是否满足要求
    private static boolean checkString(String s, Predicate<String> p) {
//        return p.test(s);
//        return !p.test(s);
        return p.negate().test(s);
    }
}

and方法与or方法:

import java.util.function.Predicate;

public class PredicateDemo2 {
    public static void main(String[] args) {
        boolean b1 = checkString("hello", s -> s.length() > 8);
        System.out.println(b1);

        boolean b2 = checkString("hello", s -> s.length() < 8);
        System.out.println(b2);

        boolean b3 = checkString("hello", s -> s.length() > 8, s -> s.length() < 8);
        System.out.println(b3);
    }

    //判断给定字符串是否满足要求
    private static boolean checkString(String s, Predicate<String> p) {
        return p.test(s);
    }

    //同一个字符串给出两个不同的判断条件,最后把这两个判断条件结果做逻辑与运算的结果作为最终的结果
    private static boolean checkString(String s, Predicate<String> p, Predicate<String> p2) {
//        return p.and(p).and(p2).test(s);   //false
        return p.or(p).or(p2).test(s);      //true
    }
}
Predicate练习
  • String[] strArray = {"张三,18","李四,20","王五,19","王麻子,21","张三丰,17"}
  • 字符串数组中有多条信息,请通过Predicate接口的拼接将符合要求的字符串选到集合ArrayList中,并遍历ArrayList集合
  • 同时满足如下要求:姓名长度大于2;年龄大于19
  • 分析
    • 有两个判断条件,所以需要使用两个Predicate接口,对条件进行判断
    • 必须同时满足两个条件,所以可以使用and方法连接两个判断条件
import java.util.ArrayList;
import java.util.function.Predicate;
public class PredicateTest {
    public static void main(String[] args) {
        String[] strArray = {"张三,18", "李四,20", "王五,19", "王麻子,21", "张三丰,17"};

        ArrayList<String> array = myFilter(strArray,
                s -> s.split(",")[0].length() > 2,
                s -> Integer.parseInt(s.split(",")[1]) > 19);
        for (String i : array){
            System.out.println(i);
        }
    }

    private static ArrayList<String> myFilter(String[] strArray, Predicate<String> p1, Predicate<String> p2) {
        ArrayList<String> array = new ArrayList<>();
        for (String i : strArray) {
            if (p1.and(p2).test(i)) {
                array.add(i);
            }
        }

        return array;
    }
}
Function接口

常用方法:

  • R apply​(T t)将此函数应用于给定的参数。
  • default Function<T,V> andThen​(Funcation after):返回一个组合函数,首先将该函数应用于其输入,然后将 after函数应用于结果。
  • Funcation<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值
import java.util.function.Function;
public class Demo {
    public static void main(String[] args) {
        Convert("50", s -> Integer.parseInt(s));
        Convert("100", Integer::parseInt);

        Convert(100, i -> String.valueOf(i + 20));

        Convert("66", s -> Integer.parseInt(s), i -> String.valueOf(i+30));
    }

    //定义一个方法,把一个字符串转换int类型,控制台输出
    private static void Convert(String s, Function<String, Integer> fun) {
        int apply = fun.apply(s);
        System.out.println(apply);
    }

    //定义一个方法,把一个int类型的数据加上一个整数之后,转为字符串在控制台输出
    private static void Convert(int i, Function<Integer, String> fun) {
        String s = fun.apply(i);
        System.out.println(s);
    }

    //定义一个方法,把一个字符串转换int类型,把int类型的数据加上一个整数之后,
    // 转换字符串在控制台输出
    private static void Convert(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
//        Integer i = fun1.apply(s);
//        String ss = fun2.apply(i);
//        System.out.println(ss);

        String ss = fun1.andThen(fun2).apply(s);
        System.out.println(ss);
    }
}
练习
  • String = "张三, 20"
  • 操作
    1. 将字符串截取得到年龄部分
    2. 将上一步得年龄转换成为int类型的数据
    3. 将上一步的int数据加10,得到一个int结果,在控制台输出
  • 使用Funcation实现

import java.util.function.Function;

public class Demo {
    public static void main(String[] args) {
        Convert("张三,20",s -> s.split(",")[1],s -> Integer.parseInt(s),i -> (i+10));

    }
    private static void Convert(String s, Function<String,String> fun1,Function<String,Integer> fun2,Function<Integer,Integer> fun3){
        int i = fun1.andThen(fun2).andThen(fun3).apply(s);
        System.out.println(i);
    }
}
原文地址:https://www.cnblogs.com/Hz-z/p/13086999.html