这里不得不提的一个点,叫做编程范式,即一类典型的编程风格,那么有哪些比较通用的范式呢 这个其实很好理解,计算机硬件运行指令的方式,就是命令式的,而高级语言中,常用的循环语句,条件语句,就属于这类,即告诉计算机硬件一步一步要去怎样做。 声明式编程是以数据结构的形式来表达程序执行的逻辑,即告诉计算机应该要做什么,常见的形式:SQL(结构化查询语言) 函数式编程跟声明式有同样的指导思想,即关注要做什么,但函数式提现函数为第一公民的原则,值得注意的事这里的函数术语指的是一种映射关系,也就是数学中的函数而非计算机中的函数。这里我们可以用一种更简单的方式去对比理解,面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象。 函数式编程关心数据的映射,命令式编程关心解决问题的步骤。 举例说明之: 有三个”字符串”都说自己比较长,那么到底谁最长? 我们来拆分一下(注意方法名的含义) 1. Stream.of(“我长”,“我才长”,“你两都没有我长”):构建了这三个字符组成的流。 简单的一行代码就完成了这个需求,同时轻松易读,何乐而不为之!!! 首先我们得明白一点,函数式编程,是可以借助lambda表达式去实现的,所以理解lambda表达式就是一个重点了,而lambda表达式的规则是函数式接口了。 函数式接口:只包含了一个抽象方法的接口。 @FunctionalInterface 注解仅用于标识该接口为函数接口,让编译器能够检查是否符合一个抽象方法。 定义了函数式接口后,就要使用了,语法格式如: (parameters) -> expression 或 (parameters) -> { expression } 实现: 简单理解的话,就是一种语法糖,对比平时我们用的匿名内部类: 接口: 实现: 接口: 实现: 接口: 实现: 通过前面的例子,应该不难发现,参数是没有带有类型的,因为编译器可以通过原先定义的方法判断参数类型,也就是类型推断,有的时候,你想知道具体类型的话,也可以加上,如: Java8为了使lambda表达式更加精简,提供了方法引用,前提是,lambda表达式只有一行,其语法格式: 首先方法引用是惰性的,包括前面定义的各种形式,都是惰性的,因为它们仅仅是定义了,并没有真正开始执行,那么怎样才算调用执行,拿上个例子说明: 接着,让我们看看方法引用怎么用,还是用多参数的例子, 实现: 调用仍然是: 留下个问题,大家思考下,我上述例子对应的是方法引用的那种类型呢? 我们上述例子,都是围绕自定义的“窃.格瓦拉”函数式接口,难道我们用lambda表达式,就非要自己定义么,当然不是,Java8内置了很多函数式接口,这里举主要的几个(其他的是这几种接口的变式,大同小异,详细可参考菜鸟教程的函数式接口),进行说明。(注意:每个函数式接口仅列举了一个方法,其他的方法使用,建议看源码或者Java8 API) 定义一个具体的“窃.格瓦拉”来说明,跟上面其他例子关联不大,仅仅为了延续上面的风格,方便理解。 消费: 消费结果 结合上面Consumer<T>的例子,如下: 结果: Predicat常用于判断的场景,比如说,判断当前输入数字是否大于100。(对不起,”窃.格瓦拉”的例子,在这实在编不出来了) 结果: 初次写博客,水平有限,有问题,还望不吝赐教!!!欢迎大家留言讨论,同时欢迎转载,但请注明出处和作者。0202年了,还没有用上Java函数式编程!!!——Lambda表达式
函数式编程是什么
命令式编程(Imperative)
声明式编程(Declarative)
函数式编程(Functional)
总结
函数式编程的好处
Stream.of("我长","我才长","你两都没有我长").mapToInt(String::length).summaryStatistics().getMax()
2. mapToInt(String::length): 转化每个字符的长度(int类型)。
3. summaryStatistics(): 统计前面的长度数据。
4. getMax(): 获取最大的长度。Lambda表达式
函数式接口
举个栗子,我们的“精神领袖”——“”窃.格瓦拉“”,就是不打工(对不起!!!)
/** * <Description> “精神领袖”——“窃.格瓦拉”,用于展示函数式接口,不打工是我们唯一的抽象方法 <br> * @author 妖帝艾雷诺 <br> * @version 1.0 <br> * @createDate 2020/04/20 16:42 <br> */ @FunctionalInterface public interface CheGuevara { /** * 不打工 */ void notWork(); }
五种形式
1.无参数
CheGuevara cheGuevara = ()-> System.out.println("这辈子都不可能打工的!!!");
CheGuevara cheGuevara = new CheGuevara() { @Override public void notWork() { System.out.println("这辈子都不可能打工的!!!"); } };
2.有单个参数
/** * 不打工 (单参数) * @param electromobile 电瓶车 */ void notWork(String electromobile);
CheGuevara cheGuevara = (electromobile)-> System.out.println("这辈子都不可能打工的!!! 我只想拿【"+electromobile+"】");
3.有多个参数
/** * 不打工(多参数) * @param electromobile 电瓶车 * @param bicycle 自行车 */ void notWork(String electromobile, String bicycle);
CheGuevara cheGuevara = (electromobile, bicycle)-> System.out.println("这辈子都不可能打工的!!! 我想拿【"+electromobile+"】和拿【"+bicycle+"】");
4.实现有多行
/** * 不打工(多参数) * @param electromobile 电瓶车 * @param bicycle 自行车 */ void notWork(String electromobile, String bicycle);
CheGuevara cheGuevara = (electromobile, bicycle)-> { System.out.println("这辈子都不可能打工的!!!"); System.out.println("我想拿【"+electromobile+"】"); System.out.println("还要拿【"+bicycle+"】"); };
5.带类型
CheGuevara cheGuevara = (String electromobile, String bicycle)-> { System.out.println("这辈子都不可能打工的!!!"); System.out.println("我想拿【"+electromobile+"】"); System.out.println("还要拿【"+bicycle+"】"); };
方法引用
类型
示例
对应lambda表达式
引用静态方法
某类名::静态方法
(a,b,…)-> 某类名.静态方法(a,b,…)
引用某个对象的实例方法
某对象::实例方法
(a,b,…)-> 某对象.实例方法(a,b,…)
引用当前参数对象的实例方法(第一个参数)
a::实例方法
(a,b,…)-> a.实例方法(b,…)
引用构造方法
某类名::new
(a,b,…)-> new 某类名(a,b,…)
cheGuevara.notWork("某某牌电动车", "某某牌自行车");
接口: /** * 不打工(多参数) * @param electromobile 电瓶车 * @param bicycle 自行车 */ void notWork(String electromobile, String bicycle); /** * 不打工(Java8接口静态方法,用于展示“方法引用”, 不一定非要在这个接口写实现方法,也可以用其他类) * @param electromobile 电瓶车 */ static void staticNotWork(String electromobile, String bicycle){ System.out.println("这辈子都不可能打工的!!!我想拿【"+electromobile+"】和拿【"+bicycle+"】"); }
CheGuevara cheGuevara = CheGuevara::staticNotWork;
cheGuevara.notWork("某某牌电动车", "某某牌自行车");
当然,像伟大的IntelliJ IDEA有智能的提示,如果发现你的lambda表达式里能够转化为更精简的方法引用的话。常用内置函数式接口
内置函数式接口
描述
Supplier<T>
无参数,返回一个T类型结果
Consumer<T>
代表了接受一个输入T类型参数并且无返回的操作
Function<T,R>
接受一个输入T类型参数,返回一个R类型结果
Predicate<T>
接受一个输入T类型参数,返回一个布尔值结果
/** * <Description> 一位看似忠诚的“窃.格瓦拉”的信仰者 <br> * * @author 妖帝艾雷诺 <br> * @version 1.0 <br> * @createDate 2020/04/20 23:12 <br> */ public class CheGuevaraImpl implements CheGuevara{ @Override public void notWork(String electromobile, String bicycle) { System.out.println("这辈子都不可能打工的,哪怕你连一百块都不给我!!!但我不拿【"+electromobile+"】也不拿【"+bicycle+"】"); } }
Supplier< T >
//利用Supplier定义一个的"窃.格瓦拉",用方法引用简化new操作 Supplier<CheGuevaraImpl> cheGuevaraSupplier = CheGuevaraImpl::new;
Consumer< T >
//定义一个消费行为,怎么消费的(惰性,还未执行) Consumer<CheGuevaraImpl> cheGuevaraImplConsumer = cheGuevaraImpl1 -> { System.out.println("花了一百块钱,买醉。没钱了!!!"); }; //接收Supplier提供的一个具体的"窃.格瓦拉",然后作为消费者,进行真实消费 (真正执行) cheGuevaraImplConsumer.accept(cheGuevaraSupplier.get());
花了一百块钱,买醉。没钱了!!!
Function< T ,R >
Function<CheGuevaraImpl, String> cheGuevaraStringFunction = cheGuevaraImpl2->{ //输入消费(利用上面定义的消费行为,对当前输入的"窃.格瓦拉"进行接收) cheGuevaraImplConsumer.accept(cheGuevaraImpl2); //输出 return "吐了"; }; //接收Supplier提供的一个具体的"窃.格瓦拉",然后作为消费者,进行真实消费,并输出 String output = cheGuevaraStringFunction.apply(cheGuevaraSupplier.get()); System.out.println(output);
花了一百块钱,买醉。没钱了!!! 吐了
Predicate< T >
Predicate<Integer> integerPredicate = x-> x > 100; System.out.println("50 > 100 = "+integerPredicate.test(50));
50 > 100 = false
总结
最后
所有示例,上传至 https://github.com/zhiwen-li/Exemplar-learning参考
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算