JDK8新特性-函数式接口

JDK8新特性-函数式接口

1.函数式接口

1.1函数式接口的概念及定义

概念:

有且只有一个抽象方法的接口,就是函数式接口

当然可以有静态方法或私有方法

定义:

public interface 接口名称 {
    public abstract 返回值类型 方法名称();  
}

1.2@FunctionalInterface

该注解用于标注函数式接口

作用:检测是否是函数式接口

如果是:编译成功

如果不是:编译失败(报错)

1.3实现函数式接口的三种方式

1.3.1编写实现类

public class MyFunctionInterfaceImpl implements MyFunctionInterface {
    @Override
    public void show() {
        System.out.println("hello!!");
    }
}

1.3.2匿名内部类

MyFunctionInterface mfi = new MyFunctionInterface() {
            @Override
            public void show() {
                System.out.println("hello 匿名内部类!!");
            }
        };
        mfi.show();

1.3.2lambda表达式

MyFunctionInterface mfi = ()->{
            System.out.println("hello lambda!!");
        };
        mfi.show();

1.4lambda表达式介绍

作用:lambda表达式可以实现函数式接口中的方法

1.4.1lambda表达式的使用场景:

lambda表达式只能在函数式接口的支持下使用(接口只有一个抽象方法)

1.4.2lambda表达式的语法格式:

lambda表达式被 -> 箭头符号分成左右两部分

左边():代表的就是函数式接口中的参数列表

右边 {}: 代表我要实现的方法的方法体

1.语法格式一:只有一个参数

(String msg)->{
     System.out.println(msg);
};

2.语法格式二:多个参数

(String name,int age)->{
    System.out.println("姓名:"+name+",年龄:"+age);
};

3.语法格式三:带有返回值

(String name,int age)->{
    return "姓名:"+name+",年龄:"+age;
};

4.语法格式四:参数的类型可以省略,因为jdk可以自动类型推断

(msg)->{
    System.out.println(msg);
};

5.语法格式四:如果参数只有一个可以省略()

msg->{
   System.out.println(msg);
};

6.语法格式五:如果方法体中只有一条语句,{},return也是可以省略的

//省略{}
msg->System.out.println(msg);
//省略return语句
(name,age)->"姓名:"+name+",年龄:"+age;

1.5JDK中提供的常用的函数式接口

1.5.1.Interface Supplier

位于java.util.function 包下,称之为生产型接口

通常给该接口的泛型指定什么类型,通过get方法就可以返回该类型的数据。

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

需求:使用Supplier接口作为方法的参数,求数组的最大值

 public static Integer getMax(Supplier<Integer> supplier){
        return supplier.get();
    }

    public static void main(String[] args) {
       int maxVal = getMax(()->{
            //计算数组的最大值
            int[] arr = new int[]{2,80,38,20};
            int max = arr[0];
            for (int i = 0; i < arr.length; i++) {
                if(arr[i]>max){
                    max=arr[i];
                }
            }
            return max;
        });
        System.out.println(maxVal);
    }
1.5.2.Interface Consumer

位于java.util.function 包下,该接口是一个消费型的接口

public interface Consumer<T> {
    void accept(T t);
    }

可以通过accept方法消费泛型指定的类型。

需求:使用Consumer接口作为方法的参数,对字符串实现翻转

public class TestFunInterface2 {
    //需求:使用Consumer接口作为方法的参数,对字符串实现翻转
    public static void revString(String str, Consumer<String> consumer){
        consumer.accept(str);
    }

    public static void main(String[] args) {
        revString("zhangsan",(str)->{
            StringBuilder reverseStr = new StringBuilder(str).reverse();
            System.out.println("翻转后的字符串:"+reverseStr);
        });
    }
}

默认方法:andThen()

该方法作用将两个Consumer接口连接在一起,然后在进行消费

public class TestFunInterface3 {
    public static void method(String s, Consumer<String> con1,Consumer<String> con2){
        //con1.accept(s);
        //con2.accept(s);
        con1.andThen(con2).accept(s); //谁在前面谁先消费
    }

    public static void main(String[] args) {
       method("zhangsan",(str)->{
           System.out.println(str.toUpperCase());
       },(str)->{
           System.out.println(str.toLowerCase());
       });
    }
}

1.5.3.Interface Predicate

位于java.util.function 包下,主要是用来进行一个判断,

通过test方法进行判断,如果成功,返回true,如果失败返回false;

public interface Predicate<T> {
    boolean test(T t);
}

需求:使用Predicat接口作为方法的参数,实现对一个字符的长度进行判断

public class TestFunInterface4 {
    //需求:使用Predicat接口作为方法的参数,实现对一个字符的长度进行判断
    public static boolean checkStr(String s, Predicate<String> predicate){
       return predicate.test(s);
    }

    public static void main(String[] args) {
        boolean result = checkStr("zha", (str) -> {
            return str.length() > 5;
        });
        System.out.println(result);
    }
}

逻辑运算符

&&:与

||:或

!:非

默认方法and()、or()、negate()

and() :等价&&

or() :等价 ||

negate() :等价 !

需求:判断一个字符串的长度是否大于5,并且判断该字符串中是否包含a

public class TestFunInterface5 {
    //需求:判断一个字符串的长度是否大于5,并且判断该字符串中是否包含a

    /*分析:1.与 操作,可以使用&& 或使用and()方法去实现
           2.我们可以传递两个Predicate类型的参数,
            第一个参数用来判断字符串的长度是否大于5
            第一个参数用来判断该字符串中是否包含a
    */
    public static boolean checkString(String s,
                                      Predicate<String> predicate1,
                                      Predicate<String> predicate2){
        //predicate1.test(s)&&predicate2.test(s);
        return predicate1.and(predicate2).test(s);
    }
    public static void main(String[] args) {
        boolean b = checkString("zha",(s)->{
            return s.length()>5;
        },(s)->{
            int i = s.indexOf("a");
            if(i>0){
                return true;
            }else{
                return false;
            }
        });
        System.out.println(b);
    }
}
1.5.4.Interface Function<T,R>

位于java.util.function 包下,转化接口,两个类型的泛型,

根据一种数据类型得到另一种类型的数据

public interface Function<T, R> {
    R apply(T t);
}

需求:将String类型的整数转化成int类型的整数

public class TestFunInterface6 {
    //需求:将String类型的整数转化成int类型的整数
    public static Integer convert(String a,
                                  Function<String,Integer> function){
        return function.apply(a);
    }

    public static void main(String[] args) {
        int a = convert("123",(s)->{
            return Integer.parseInt(s);
        });
        System.out.println(a);
    }
}

默认方法:andThen()

该方法作用将两个Function接口连接在一起

需求:将String类型的数据转换成Integer类型,加10之后,再将其转换成String类型

public class TestFunInterface7{
    //需求:将String类型的数据转换成Integer类型,加10之后,再将其转换成String类型
    /*
    * 分析:
    * 涉及到两次转换:
    * 1.String类型的数据转换成Integer类型
    * 使用Function接口进行转换 Integer apply(String)
    * 2.加10之后,再将其转换成String类型
    * 使用Function接口进行转换 String apply(Integer)
    * 使用andThen()方法来连接这两个Function接口
     */
    public static String convert(String s, Function<String,Integer> fun1,
                                 Function<Integer,String> fun2){
        return fun1.andThen(fun2).apply(s);
    }

    public static void main(String[] args) {
        String str = convert("123",(s)->{
            return Integer.parseInt(s)+10;
        },(i)->{
            return i.toString();
        });

        System.out.println(str);
    }

}

2.Stream流

1.简介

流(Stream)到底是什么呢?

是数据渠道,**用于操作数据源(集合、数组等)**所生成的元素序列。

注意:

Stream自己不会存储元素。

Stream不会改变源对象。相反,他们会返回一个持有结果的新 Stream

Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

延迟执行:多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

2.三个步骤

  • 创建 Stream流

    一个数据源(如:集合、数组),获取一个流

    1.通过Collection系列集合提供的stream()

    2.通过Arrays中的静态方法stream()获取数组流

    3.通过Stream类中的静态方法of()

  • 中间操作

    一个中间操作链,对数据源的数据进行处理

  • 终止操作(终端操作)

    一个终止操作,执行中间操作链,并产生结果

3.中间操作-筛选与切片

filter: 接收 Lambda,从流中排除某些元素。

limit(n) : 截断流,使其元素不超过给定数量n。

skip(n) : 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补

distinct : 筛选,通过流所生成元素的 hashCode()和 equals()去除重复元素

public static void main(String[] args) {
        //filter : 查询年龄小于等于20岁的员工信息
        /*Stream<Employee> stream1 = employees.stream()
                .filter((employee) -> {
                    System.out.println("中间操作");
                    return employee.getAge() <= 20;
                });*/

        //limit: 限定返回两条数据
        Stream<Employee> stream1 = employees.stream()
                .filter((employee) -> {
                    System.out.println("中间操作");
                    return employee.getAge() <= 20;
                })
                .limit(2);//做了一个短路的处理

        stream1.forEach((e)->{
            System.out.println(e);
        });
    }

4.中间操作-映射

map :接收 Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

flatMap : 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

public static void main(String[] args) {
        //**map** :接收 Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,
        // 该函数会被应用到每个元素上,并将其映射成一个新的元素。
        //提取员工的姓名
        employees.stream()
                .map((employee)->{
                    return employee.getName();
                })
                .forEach((e)->{
                    System.out.println(e);
                });
    }

5.中间操作-排序

sorted() : 自然排序

sorted(Comparator com) : 定制排序

 public static void main(String[] args) {
        //**sorted()** : 自然排序 int类型、String类型
        //**sorted(Comparator com)**  : 定制排序
        /*List<String> s = Arrays.asList("ccc","bbb","aaa","hhh");
        s.stream().sorted().forEach((e)->{
            System.out.println(e);
        });*/

        employees.stream()
                .sorted((e1,e2)->{
                   return e1.getAge()-e2.getAge();
                }).forEach(e-> System.out.println(e));
    }

6.终止操作-查找与匹配

allMatch 检查是否匹配所有元素

anyMatch 检查是否至少匹配一个元素

noneMatch 检查是否没有匹配所有元素

findFirst 返回第一个元素

findAny 返回当前流中的任意元素

count 返回流中元素的总个数

max 返回流中最大值

**min ** - 返回流中最小值

3.方法引用

什么是方法引用

若 Lambda体中的内容有方法已经实现了,我们可以使用方法引用(可以理解为方法引用是 Lambda表达式的另外一种表现形式)

主要有三种语法格式:

对象::实例方法名

public static void main(String[] args) {
        /*void accept(String t);  public void println(String x)
        使用方法引用需要保证两个方法的返回值类型一致 且 参数类型要一致
         */

        //Consumer<String> consumer = (x)-> System.out.println(x);
        //对象::实例方法名
        /*PrintStream ps = System.out;
        Consumer<String> consumer = ps::println;

        consumer.accept("hello world!!");*/

        Employee e = new Employee("张三丰",100,20000);
        // String get();
        //Supplier<String> supplier = ()->{return e.getName();};
        Supplier<String> supplier = e::getName;
        String name = supplier.get();
        System.out.println(name);

    }

类::静态方法名

  public static void main(String[] args) {
        //Comparator<Integer>  comparator = (x,y)->Integer.compare(x,y);
        //类::静态方法名
        Comparator<Integer>  comparator = Integer::compare;
        int result = comparator.compare(20, 10);
        System.out.println(result);

    }

类::实例方法名

public static void main(String[] args) {
    //比较两个字符串是否相同
    BiPredicate<String,String> biPredicate1 = (x,y)->x.equals(y);
    //类::实例方法名
    /*
    * 什么时候可以使用这种方式:
    * 传递的两个参数,第一个参数必须是方法的调用者,第二个参数是方法的参数
    * */

    BiPredicate<String,String> biPredicate2 = String::equals;
    boolean test = biPredicate2.test("hello", "hello");
    System.out.println(test);
}
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值