• Java进阶知识复习笔记(三):函数式编程


    一、lambda表达式

    • lambda表达式:

    一个 lambda 表达式具有下面这样的语法特征。它由三个部分组成:第一部分为一个括号内用逗号分隔的参数列表,参数即函数式接口里面方法的参数;第二部分为一个箭头符号:->;第三部分为方法体,可以是表达式和代码块。语法如下:

    parameter -> expression body
    
    • 1
    • 函数式接口:

    函数接口是一种只有一个方法的接口,可以隐式地转换成 Lambda 表达式。函数接口的存在使得方法代码作为数据被对待。

    • 代码展示函数式接口和lambda表达式的使用:
    package com.tracy.algorithmeditionfour.chapter1;
    
    public class Operator {
        interface MathOperation{
            int operation(int a,int b);
        }
    
        private int operate(int a,int b,MathOperation mathOperation){
            return mathOperation.operation(a,b);
        }
    
        public static void main(String[] args) {
            Operator operator = new Operator();
            /**
             * 下面展示函数式接口和lambda表达式的语法:
             * 四个句子分别实现加、减、乘、除功能,语法不同但效果是类似的。
             */
            MathOperation add = (a, b) -> a + b;//不指定参数类型,不使用return关键词
            MathOperation sub = (int a, int b) -> a - b;//指定参数类型
            MathOperation multi = (a, b) -> {//使用return关键词,同时也必须使用大括号
                return a * b;
            };
            MathOperation div = (a, b) -> a / b;
            /**
             * 调用函数式接口
             */
            System.out.println("2+3="+operator.operate(2,3,add));
            System.out.println("2-3="+operator.operate(2,3,sub));
            System.out.println("2*3="+operator.operate(2,3,multi));
            System.out.println("2/3="+operator.operate(2,3,div));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    运行结果:

    2+3=5
    2-3=-1
    2*3=6
    2/3=0
    
    • 1
    • 2
    • 3
    • 4
    • 方法引用:

    方法引用可以通过方法的名字来引用其本身。它可以用来引用下列类型的方法:

    (1)构造器引用。语法是 Class::new,或者更一般的 Class< T >::new,要求构造器方法是没有参数。
    (2)静态方法引用。语法是 Class::static_method,要求接受一个 Class 类型的参数。
    (3)特定类的任意对象方法引用。它的语法是 Class::method,要求方法是没有参数的。
    (4)特定对象的方法引用,它的语法是 instance::method。要求方法接受一个参数,与 3 不同的地方在于,3 是在列表元素上分别调用方法,而 4 是在某个对象上调用方法,将列表元素作为参数传入。
    
    • 1
    • 2
    • 3
    • 4
    • 代码展示方法引用:
     List<String> names = new ArrayList<>();
    
            names.add("Peter");
            names.add("Linda");
            names.add("Smith");
            names.add("Zack");
            names.add("Bob");
    
            //     通过 System.out::println 引用了输出的方法
            names.forEach(System.out::println);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果:

    Peter
    Linda
    Smith
    Zack
    Bob
    
    • 1
    • 2
    • 3
    • 4
    • 5

    二、函数式接口

    • 函数式编程

    java.util.Funtion包中,有许多和函数式编程相关的API,这里我就不列举了。

    下面展示下函数式编程:

    package com.tracy.algorithmeditionfour.chapter1;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    public class FunctionDev {
        public static void eval(List<Integer> list, Predicate<Integer> predicate){
            for(Integer i:list){
                if(predicate.test(i)){
                    System.out.println(i);
                }
            }
        }
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
            System.out.println("全部数字:");
            //等同于list.forEach(n -> System.out.println(n));
            eval(list,n->true);
            System.out.println("偶数:");
            //等同于list.forEach(n ->{if(n%2==0) System.out.println(n);});
            eval(list,n->n%2==0);
            System.out.println("奇数:");
            //等同于list.forEach(n ->{if(n%2==1) System.out.println(n);});
            eval(list,n->n%2==1);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    运行结果:

    全部数字:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    偶数:
    2
    4
    6
    8
    10
    奇数:
    1
    3
    5
    7
    9
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 默认方法:

    Java 8 引入默认方式使得 List 和 Collection 接口能够拥有 forEach 方法的默认实现。实现了这些接口的类也不必再实现相同的功能了。

    public interface Girl{
       default void print(){
          System.out.println("I am a goy.");
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 代码展示:
    public class NewFeaturesTester{
        public static void main(String args[]){
            Younger younger = new Student();
            younger.print();
        }
    }
    
    interface Younger{
        default void print(){
            System.out.println("I am a younger.");
        }
    
        static void sayHi(){
            System.out.println("Young is the capital.");
        }
    }
    
    interface Learner{
        default void print(){
            System.out.println("I am a learner.");
        }
    }
    
    class Student implements Younger, Learner{
        public void print(){
            Younger.super.print();
            Learner.super.print();
            Younger.sayHi();
            System.out.println("I am a student!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    运行结果:

    I am a younger.
    I am a learner.
    Young is the capital.
    I am a student!
    
    • 1
    • 2
    • 3
    • 4

    三、Optional 类

    在 Java 官方文档的解释中,它是一个可以为 null 的容器对象。如果值存在则 isPresent() 方法会返回 true,调用 get()方法会返回该对象。使用这个类会提高代码的鲁棒性。

    • 代码演示:
    package com.tracy.algorithmeditionfour.chapter1;
    
    import java.util.Optional;
    
    public class Option_test {
        public Integer sum(Optional<Integer> a,Optional<Integer> b){
            System.out.println("a存在:"+a.isPresent());
            System.out.println("b存在:"+b.isPresent());
            Integer value_a=a.orElse(new Integer(0));//如果a为null则返回0,否则返回a
            Integer value_b=b.get();//使用这个方法的前提是b必须有正常值
            return value_a+value_b;
        }
    
        public static void main(String[] args) {
            Option_test option=new Option_test();
            Integer a=null;
            Integer b=new Integer(3);
            Optional<Integer> a_o=Optional.ofNullable(a);//允许传入null值
            Optional<Integer> b_o=Optional.ofNullable(b);//不允许传入null值
            System.out.println(option.sum(a_o,b_o));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    运行结果:

    a存在:false
    b存在:true
    3
    
    • 1
    • 2
    • 3

    四、Stream

    Java 8 引入了 Stream(流式操作),我们可以通过该操作实现对集合的并行处理和函数式操作。Collection 是一种静态的内存数据结构,而 Stream 是面向计算的。

    API的学习看这位大哥的博客:这里跳转

  • 相关阅读:
    配置git在Linux服务器上
    MongoDB(一)之Windows安装
    mysql case when 不命中缓存
    Hadoop根据加工数据量计算Datanode数量
    Dubbo启动报错
    docker镜像编译与docker-compose部署与编排
    python barplot 比例bili scanpy
    FFplay文档解读-21-音频过滤器六
    window下杀指定端口进程
    力扣 095. 最长公共子序列(C语言+动态规划)
  • 原文地址:https://blog.csdn.net/Tracycoder/article/details/125487276