首页 > 编程语言 >函数式编程

函数式编程

时间:2024-09-08 19:46:24浏览次数:7  
标签:函数 编程 System student Student println out

目录

基本概念

合格的函数

  • input->output
  • 不引用外部可变数据(stream-final)

函数的本质是规则,函数对象固化规则,使之可传递

  1. 行为参数化
public class FunctionalPro {

    @AllArgsConstructor
    @ToString
    static class Student {
        private String name;
        private Integer age;
        private String sex;
    }

    public static void main(String[] args) {
        List<Student> list = Arrays.asList(
                new Student("张无忌",18,"男"),
                new Student("杨不悔",16,"女"),
                new Student("周芷若",19,"女"),
                new Student("宋青书",20,"男")
        );

        //lambda本质是接口的匿名实例化
        System.out.println(filter(list, student -> student.name.equals("张无忌")));

        System.out.println(filter(list, student -> student.age < 19));

        System.out.println(filter(list, student -> student.sex.equals("女")));
    }

    @FunctionalInterface //确保只有一个抽象方法
    interface Lambda {
        boolean predicate(Student student);
    }

    static private List<Student> filter(List<Student> list, Lambda pred) {
        List<Student> res = new ArrayList<>();
        for(Student student : list) {
            if(pred.predicate(student)) {
                res.add(student);
            }
        }
        return res;
    }
}
  1. 延迟执行

行为参数化后带来的结果就是可以自行选择执行时机,外部if->内部if,提高了整体性

public class FunctionalPro {

    public static void main(String[] args) {

        int logLevel = 1;

        if(logLevel == 1) {
            excute();
        }

        showLog(logLevel, () -> excute()); //等价showLog(logLevel, FunctionalPro::excute);
    }

    static void showLog(int level, Supplier<String> supplier) {
        if(level == 1) {
            System.out.println(supplier.get());
        }
    }

    static String excute() {
        System.out.println("执行耗时操作");
        return "需要的结果";
    }

}

函数对象类型

什么是函数接口(Functional Interface):a Single Abstract Method(SAM) interface

@FunctionalInterface //确保只有一个抽象方法
interface Lambda {
    boolean predicate(Student student);
}

什么是函数对象(Functional Object):函数接口(Functional Interface)的实现类

类型:

  1. lambda表达式 Lmbda lambda = student -> student.age <= 18
  2. 方法引用(现有方法转为含数据对象)
方法引用 对应的Lambda表达式 类型
Math::max (int a, int b) -> Math.max(a,b); 类的静态方法
Student::getName (Student stu) -> stu.getName(); 类的非静态方法
System.out::println (Object obj) -> System.out.println(obj); 对象的非静态方法
Student::new () -> new Student(); 对象的new方法

本质:静态方法直接调用,非静态方法需要对象调用

Jdk中已定义的函数接口:

类型 函数接口形式 对应的lambda
Runnable void run(); () -> void
Callable V call(); () -> V
Supplier T get(); [Lazy Evaluation] () -> T
Consumer void accept(T t); (T) -> void
Function<T,R> R apply(T t); (T) -> R
Predicate boolean test(T t); (T) -> boolean
BiFunction<T,U,R> R apply(T t, U u); (T, U) -> R

闭包和柯里化

闭包

捕获外部变量,变量需要时final或者effective final

public class FunctionalPro {
    public static void main(String[] args) {
        List<Runnable> list = new ArrayList<>();
        for(int i = 0; i < 10; i++) {
            int k = i + 1;
            Runnable task = () -> System.out.println(Thread.currentThread()+":执行任务"+k);
            list.add(task);
        }

        ExecutorService executorService = Executors.newCachedThreadPool();
        for(Runnable task : list) {
            executorService.submit(task);
        }
    }
}

柯里化

让接收多个参数的函数转换成一系列接收一个参数的函数(闭包传递前端参数),让函数分步执行

代码见:currying.java

高阶函数

含义:是其它函数对象的使用者。

作用:

  • 将通用、复杂的逻辑隐含在高阶函数
  • 内将易变、未定的逻辑放在外部的函数对象

实现简单流:

代码见:SimpleStream.java

Stream API

流的特性:一次使用,两类操作(中间操作 lazy,终结操作 eager)

构建与生成:

//构建流
List.stream();
Arrays.Stream();
Stream.of(1,2,3);
//生成流
IntStream.range(1,10).forEach(System.out::println);

IntStream.iterate(1, x->x+1).limit(10).forEach(System.out::println);
IntStream.iterate(1, x->x<=9, x->x+1).forEach(System.out::println);

IntStream.generate(()->ThreadLocalRandom.current().nextInt(100)).limite(10).forEach(System.out::println);
ThreadLocalRandom.current().ints(5, 0, 100).forEach(System.out::println);
    

流操作:

操作 写法
合并 Stream.of(s1, s2);
截取(分页) skip(n);
limit(n);
查找 filter(Predicate p).findAny();
filter(Predicate p).findFirst();
判断 anyMatch(Predicate p);
allMatch(Predicate p);
noneMatch(Predicate p);
去重 distinct()
排序 sorted(Comparator c);
化简 reduce(p,x) -> r);
reduce(init, (p, x) -> r);
reduce(init, (p, x) -> r, (r1, r2) -> r)
收集 collect(Supplier supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);
collect(Collector<? super T, A, R> collector);

代码见: StreamAPI.java

下游收集器:

作用 下游收集器
映射后收集 mapping(x -> y, dc);
计数 counting();
计算 summingInt(x -> int);
averageDouble(x -> double);
化简 reducing(init, (p, x) -> r);

代码见: DCollector.java

基本类型流:

  • IntStream
  • LongStream
  • DoubleStream

基本流方法:

方法 作用
intstream.mapToobj(int ->obj) 转换为obj流
stream.mapToInt(x -> int) obj流转换为基本流
intstream.boxed() 转换为Integer流
intstream.sum() 求和
intstream.min() 求最小值,返回Optional
intstream.max() 求最大值,返回optional
intstream.average() 求平均值,返回Optional
intstream.summarystatistics() 综合count sum min max average

Stream API汇总见: Stream.html

并行流

方法: .parallel()

并发收集器组成部分:

image-20240706111945124

枚举 特性
Collector.Characteristics.IDENTITY_FINISH 不需要收尾
Collector.Characteristics.UNORDERED 不需要保证顺序
Collector.Characteristics.CONCURRENT 容器需要支持并发

一般用法:

  1. CONCURRENT+UNORDERED+线程安全容器
  2. 默认 + 线程不安全容器

效率:

  • 数据量少时: 单线程收集
  • 数据量多时: 多线程Concurent收集 > 多线程非Concurrent收集
  • 处理基本类型时: 基本流 $\approx$ 普通循环 >> 普通Stream流

代码见: ParallelStream

具体应用

  1. 统计分析

代码见: AnalysisTest.java

  1. 异步处理

代码见: AsynchronousTest.java

  1. 框架设计
    • 半成品软件,帮助开发者快速构建应用程序
    • 框架提供的都是固定不变的、已知的、可以重用的代码
    • 而那些每个应用不同的业务逻辑,变化的、未知的部分,则在框架外由开发者自己实现
    • 函数对象用来传递这种可变的部分

代码见: FrameWorkTest.java 【方法引用的偏门用法:根据反射得到方法实现类】

  1. 并行计算

代码见: ParallelTest.java

原理

Lambda和MethodReference本质都是语法糖,会被翻译为类,对象,方法

类别 方法 类,对象
Lambda 编译器生成 运行时创建,内部调用生成的方法
MethodReference 已有 运行时创建,内部调用生成的方法
// -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles
// for (Method method : C01Lambda1.class.getDeclaredMethods()) {
//     System.out.println(method);
// }
public class C01Lambda1 {
    public static void main(String[] args) throws Throwable {
        BinaryOperator<Integer> lambda = (a, b) -> a + b;
        

        
        System.in.read();
    }
    
    // 类和对象:运行时生成
    static final class MyLambda implements BinaryOperator<Integer> {
        private MyLambda() {}
        @Override
        public Integer apply(Integer a, Integer b) {
            return lambda$main$2(a, b);
        }
    }

    // 方法:编译时生成
    private static Integer lambda$main$2(Integer a, Integer b) {
        return a + b;
    }
}

其他

标签:函数,编程,System,student,Student,println,out
From: https://www.cnblogs.com/timothy020/p/18403326

相关文章

  • CTF逆向:将数组作为函数代码执行
    例题攻防世界BABYREflag判定条件为这个if(v5==14&&(*judge)(s))注意judge本质上是一个数组,(*judge)(s)则说明judge数组中的内容被当做代码执行但前面又有for(i=0;i<=181;++i)judge[i]^=0xCu;judge数组中的内容进行加密所以需要进行patch......
  • Java基础第六天-面向对象编程
    类与对象类就是数据类型,对象就是一个具体的实例。类拥有属性和行为。类是抽象的,概念的,代表一类事物,比如人类,猫类等它是数据类型。对象是具体的,实际的,代表一个具体事物,即是实例。类是对象的模板,对象是类得一个个体,对应一个实例。对象在内存中的存在形式:字符串是指向地址保......
  • 算法编程题(Day01)
    1.雀魂启动!小包最近迷上了一款叫做雀魂的麻将游戏,但是这个游戏规则太复杂,小包玩了几个月了还是输多赢少。于是生气的小包根据游戏简化了一下规则发明了一种新的麻将,只留下一种花色,并且去除了一些特殊和牌方式(例如七对子等),具体的规则如下:总共有36张牌,每张牌是1~9。每个数字......
  • 深度学习|激活函数:网络表达增强
    文章目录引言常见的激活函数阶跃函数**Sigmoid****ReLU****LeakyReLU****Softmax****Tanh**恒等函数对比分析梯度问题可训练性结语引言在前文对M-P神经元结构的介绍以及「深度学习|模型推理:端到端任务处理」的推理过程演示中,我们反复提到了激活函数......
  • 哪个编程工具让你的工作效率翻倍?
    在日益繁忙的工作环境中,选择合适的编程工具已成为提升开发者工作效率的关键。不同的工具能够帮助我们简化代码编写、自动化任务、提升调试速度,甚至让团队协作更加顺畅。那么,哪款编程工具让你的工作效率翻倍?是智能的代码编辑器,强大的版本控制工具,还是那些让你事半功倍的自动化......
  • Python中的`map()`函数和`filter()`函数及其应用场景
    在Python中,map()和filter()是两个内置的高阶函数,它们接受函数作为参数,并对序列(如列表、元组等)中的每个元素应用该函数。这两个函数虽然功能相似,但在使用目的和返回结果上有所不同。下面,我将分别详细解释map()和filter()函数的工作原理、应用场景,并探讨它们的异同点。1. map()......
  • 网络属性及相关配置工具\shel脚本编程-进阶 \进程-系统性能和计划任务
    一、通过网络配置命令让主机上网1.查看网络接口信息:  -`ipa`或者`ifconfig`显示系统中所有网络接口的详细信息,包括IP地址、子网掩码、MAC地址等。2.配置IP地址、子网掩码、网关和DNS:  -IP地址:使用`ifconfig`或`ipaa`命令来设置IP地址。例如,`ifconfig......
  • 编程语言
    熟悉编程语言Top50及编程泛型1.python:是一种面向对象、解释型、动态类型计算机程序设计语言2.c:是一门面向过程的、抽象化的通用程序设计语言。3.java:是一门面向对象,解释型(但也需要编译)的编程语言。4.c++:既可C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的......
  • 并发编程数据结构-栈
    并发编程数据结构-栈有锁栈Stack1-基础线程安全栈Stack1是一个简单的线程安全栈实现,使用了std::mutex来保证push和pop操作的原子性。主要特点包括:使用std::lock_guard确保操作期间栈的线程安全。提供了两种push操作(左值引用和右值引用),优化了性能。pop操作抛......
  • MySQL 函数查询返回NULL
    createtableuser(idbigintprimarykeyauto_increment,ageint);gorm使用函数查询时,通过IFNULL来确保查询不到记录时有默认值。max函数selectmax(age)fromuser;selectIFNULL(max(age),0)fromuser;sum函数count函数默认是0。......