StudyLambda
    Lambda 指的是函数式编程,现在最为流行的编程模式为面向对象,很多的开发者并不认可面向对象,所以很多的开发者宁愿继续使用 C 语言进行开发,也不愿意使用java,c++
    但是随着整个行业的技术发展,函数编程语言已经开始被很多的人所认可,于是java也是被迫环境因素追加了 Lambda
    如果要想去理解 Lambda 表达式设置的背景,就需要首先理解匿名内部类
    匿名内部类解决的问题:对于抽象类或接口的子类如果发现其只使用一次,那么就没有必要将其定义为一个类,这样可以节约类的定义空间,但是匿名内部类太麻烦了
    
    范例:观察匿名内部类

  1. package cn.mysterious;
  2. interface IMessage{
  3. public String getMsg();
  4.  
  5. }
  6.  
  7. public class Lang0 {
  8.  
  9. public static void main(String[] args) {
  10. // TODO Auto-generated method stub
  11. IMessage msg = new IMessage() {
  12.  
  13. @Override
  14. public String getMsg() {
  15. // TODO Auto-generated method stub
  16. return "ssssssssssssssss";
  17. }
  18. };
  19. System.out.println(msg.getMsg());
  20. }
  21.  
  22. }

因为面向对象的最大特征:结构要完整,这个时候如果使用 Lambda 表达式呢?

  1. package cn.mysterious;
  2. interface IMessage{
  3. public String getMsg();
  4.  
  5. }
  6.  
  7. public class Lang0 {
  8.  
  9. public static void main(String[] args) {
  10. // TODO Auto-generated method stub
  11. IMessage msg = () ->"?????????";
  12. System.out.println(msg.getMsg());
  13. }
  14. }

一个简单的一行语句就代替了完整的结构,那么自然会有许多的追捧者去使用它
            实际上 Lambda 表达式以上的做法只是其中的一种形式,它有三种语法:
                () ->{多行语句,return 语句};
                () ->单行语句;
                () ->返回结果;
                
            范例:多行语句定义

  1. package cn.mysterious;
  2. interface IMessage{
  3. public String getMsg();
  4.  
  5. }
  6.  
  7. public class Lang0 {
  8.  
  9. public static void main(String[] args) {
  10. // TODO Auto-generated method stub
  11. IMessage msg = () ->{
  12. String str = "???????";
  13. return str;
  14. };
  15. System.out.println(msg.getMsg());
  16. }
  17.  
  18. }               

如果现在设计的接口里面没有返回值的存在,那么方法体也可以使用一行语句,可以直接避免“{}”定义

  1. package cn.mysterious;
  2. interface IMessage{
  3. public void print();
  4.  
  5. }
  6.  
  7. public class Lang0 {
  8.  
  9. public static void main(String[] args) {
  10. // TODO Auto-generated method stub
  11. IMessage msg = () -> System.out.println("???????????");;
  12. msg.print();
  13. }
  14.  
  15. }

如果要想使用 Lambda 表达式有一个重要的前提:一个接口之中只允许有一个抽象方法,如果你现在需要强制描述接口定义(某一个接口就是函数式编程接口)则可以追加一个注解

  1. package cn.mysterious;
  2. @FunctionalInterface // 是函数式接口,只允许有一个抽象方法
  3. interface IMessage{
  4. public void print();
  5.  
  6. }
  7. public class Lang0 {
  8.  
  9. public static void main(String[] args) {
  10. // TODO Auto-generated method stub
  11. IMessage msg = () -> System.out.println("???????????");;
  12. msg.print();
  13. }
  14.  
  15. }

Lambda 是基于函数式接口定义的,如果要想使用 Lambda  重要的前提:一个接口之中只允许有一个抽象方法
                
            如果有很多抽象方法呢?

  1. package cn.mysterious;
  2. @FunctionalInterface // 是函数式接口,只允许有一个抽象方法
  3. interface IMessage{
  4. public void print();
  5. public default void fun(){}
  6.  
  7. }
  8. public class Lang0 {
  9.  
  10. public static void main(String[] args) {
  11. // TODO Auto-generated method stub
  12. IMessage msg = () -> System.out.println("???????????");;
  13. msg.print();
  14. msg.fun();
  15. }
  16.  
  17. }

*/

/*    
    在之前所学习的都属于对象的引用,对象引用的本质在于:同一块堆内存空间,可以被不同的栈内存所指向
    那么方法的引用指的是一个方法可以设置不同的别名,即:可以被不同的接口的对象所使用
    对于方法的引用在java里面提供有四种处理形式:
        引用类中的静态方法:类名称 :: static 方法名称
        引用某个对象的方法;实例化对象 :: 普通方法
        引用某个特定的方法:类名称 :: 普通方法
        引用构造方法:类名称 :: 普通方法
        
    范例:引用静态方法
        String 类有一个 valueOf() 方法,该方法可以将接收到的基本数据类型变为字符串
            方法定义: public static String valueOf(数据类型 变量);

  1. package cn.mysterious;
  2. /**
  3. * 进行以函数式接口定义
  4. * @author mldn
  5. * @param <P> 引用方法的参数类型
  6. * @param <R> 引用方法的返回值定义
  7. */
  8. @FunctionalInterface // 是函数式接口,只允许有一个抽象方法
  9. interface IUtile<P,R>{
  10. public R convert(P p); // 做新的方法
  11.  
  12. }
  13. public class Lang0 {
  14.  
  15. public static void main(String[] args) {
  16. // TODO Auto-generated method stub
  17. IUtile<Integer,String> objA = String :: valueOf; // 方法引用
  18. System.out.println(objA.convert(100));
  19. }
  20.  
  21. }

也可以使用 Integer,parseInt() 转换

  1. package cn.mysterious;
  2. public class Lang0 {
  3.  
  4. public static void main(String[] args) {
  5. // TODO Auto-generated method stub
  6. IUtil<Integer,String> objA = String :: valueOf; // 方法引用
  7. System.out.println(fun(objA,100).length());
  8. }
  9. public static <P,R> R fun(IUtil<P,R> temp,P p){
  10. return temp.convert(p);
  11. }
  12.  
  13. }
  14. /**
  15. * 进行以函数式接口定义
  16. * @author mldn
  17. * @param <P> 引用方法的参数类型
  18. * @param <R> 引用方法的返回值定义
  19. */
  20. @FunctionalInterface // 是函数式接口,只允许有一个抽象方法
  21. interface IUtil<P,R>{
  22. public R convert(P p); // 做新的方法
  23.  
  24. }

以上只是引用了一个简单的 static 方法,也可以直接引用某一个类中的方法
        
        范例:引用 String 类中的字符串转大写方法
            [“字符串”.toUpperCase] public String toUpperCase();

  1. package cn.mysterious;
  2.  
  3. @FunctionalInterface // 是函数式接口,只允许有一个抽象方法
  4. interface IUtil<R>{
  5. public R upper(); // 做新的方法
  6.  
  7. }
  8. public class Lang0 {
  9.  
  10. public static void main(String[] args) {
  11. IUtil<String> obj = "hello" :: toUpperCase;
  12. System.out.println(obj.upper());
  13. }
  14. }

范例:引用类中的普通方法
            String 类有一个 compareTo() 方法,这个方法是一个普通方法,而且需要两个参数比较
                方法: public int compareTo(String str);

  1. package cn.mysterious;
  2.  
  3. @FunctionalInterface // 是函数式接口,只允许有一个抽象方法
  4. interface IUtil<R,P>{
  5. public R compare(P p1,P p2); // 做新的方法
  6.  
  7. }
  8. public class Lang0 {
  9.  
  10. public static void main(String[] args) {
  11. IUtil<Integer,String> obj = String :: compareTo;
  12. System.out.println(obj.compare("A","a"));
  13. }
  14. }

以上使用的都是类的结构,而整个设计里面最大的亮点在于构造方法也可以设置别名引用
            
        范例:引用构造方法

  1. package cn.mysterious;
  2. @FunctionalInterface // 是函数式接口,只允许有一个抽象方法
  3. interface IUtil<R,FP,SP>{
  4. public R create(FP p1,SP p2); // 做新的方法
  5.  
  6. }
  7. public class Lang0 {
  8.  
  9. public static void main(String[] args) {
  10. IUtil<Member,String,Integer> obj = Member :: new; // 引用构造
  11. System.out.println(obj.create("????",20));
  12. }
  13.  
  14. }
  15. class Member{
  16. private String name;
  17. private int age;
  18. public Member(String name,int age) {
  19. this.name = name;
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Member [name=" + name + ", age=" + age + "]";
  25. }
  26. }

Lambda 表达式的操作除了可以自定义方法体之外,用户也可以去引用已经实现好的类中的方法
            
    
    内建函数式接口
        函数式接口是 Lambda 实现关键所在,但是很多时候如果要想进行一个项目设计的时候,肯定需要许多标准的函数式接口
        所以在java设计过程之中考虑到用户使用标准型问题,所以也提供有四个内建的函数式接口
            功能性函数接口: public Interface Function<T,R>{R apply(T t)}
            消费型函数接口: public interface Consumer<T>{public void accept(T t)}
            供给性函数接口: public interface Supplier<T>{public T get()}
            断言型函数接口: public interface Predicate<T>{public boolean test(T t)}
            
        范例:使用功能型接口

  1. package cn.mysterious;
  2.  
  3. import java.util.function.Function;
  4.  
  5. public class Lang0 {
  6.  
  7. public static void main(String[] args) {
  8. Function<Integer,String> obj = String :: valueOf;
  9. System.out.println(obj.apply(100));
  10. }
  11.  
  12. }

实际上在 java.util.function 开发包里面有许多扩展的函数式接口,可以帮助用户简化定义
        
        范例:使用 IntFunction

  1. package cn.mysterious;
  2.  
  3. import java.util.function.IntFunction;
  4. public class Lang0 {
  5.  
  6. public static void main(String[] args) {
  7. IntFunction<String> obj = String :: valueOf;
  8. System.out.println(obj.apply(100));
  9. }
  10.  
  11. }

范例:消费型接口,现在学习到的消费处理只有一个方法:打印输出

  1. package cn.mysterious;
  2.  
  3. import java.util.function.Consumer;
  4. import java.util.function.IntFunction;
  5. public class Lang0 {
  6.  
  7. public static void main(String[] args) {
  8. Consumer<String> obj = System.out :: println;
  9. obj.accept("?????");
  10. }
  11.  
  12. }

范例:供给型,字符串转大写或小写(“Hello” .toLowerCase())

  1. package cn.mysterious;
  2.  
  3. import java.util.function.Supplier;
  4.  
  5. public class Lang0 {
  6.  
  7. public static void main(String[] args) {
  8. Supplier<String> obj = "Hello" :: toLowerCase;
  9. System.out.println(obj.get());
  10.  
  11. }
  12.  
  13. }

范例:断言型接口( startsWith() 方法,返回boolean,接收一个字符串)

  1. package cn.mysterious;
  2.  
  3. import java.util.function.Predicate;
  4.  
  5. public class Lang0 {
  6.  
  7. public static void main(String[] args) {
  8. Predicate<String> obj = "##hello" :: startsWith;
  9. System.out.println(obj.test("##"));
  10. }
  11.  
  12. }

如果不去考虑标准,这些接口完全可以自己来实现,而这四个接口是 java 中进行 Lambda 编程时所采用的标准接口

菜鸡的Java笔记 第三十六 - java 函数式编程的更多相关文章

  1. 菜鸡的Java笔记 第三十二 - java 静态导入的实现

    静态导入的实现        为了理解静态导入的操作产生的动机,下面通过一个具体的代码来观察        范例:现在有一个 Import 的类,这个类中的方法全部都是 static 方法 packa ...

  2. Java从零开始学三十六(JAVA IO- 字符流)

    一.字符流 BufferedReader:BufferedReader是从缓冲区之中读取内容,所有的输入的字节数据都将放在缓冲区之中 BufferedWriter:把一批数据写入到缓冲区,当缓冲区区的 ...

  3. Java开发学习(三十六)----SpringBoot三种配置文件解析

    一. 配置文件格式 我们现在启动服务器默认的端口号是 8080,访问路径可以书写为 http://localhost:8080/books/1 在线上环境我们还是希望将端口号改为 80,这样在访问的时 ...

  4. “全栈2019”Java多线程第三十六章:如何设置线程的等待截止时间

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 下一章 "全栈2019"J ...

  5. 菜鸡的Java笔记 第三十四 Annotation

    Annotation        多例模式特点:            1. 多例类可以有多个实例            2. 多例类必须自己创建自己的实例,并管理自己的实例,和向外界提供自己的实例 ...

  6. 菜鸡的Java笔记 第三十 - java 异常的捕获及处理

    异常的捕获及处理        1.异常的产生分析以及所带来的影响        2.异常的处理的基本格式        3.异常的处理流程        4.异常的处理模式        5.自定义 ...

  7. 菜鸡的Java笔记 第三十五 接口定义增强

    接口定义增强        在java从一开始到现在接口之中的核心组成部分:抽象方法与全局常量,但是随着技术的不断发展,用户在使用过程之中发现了有一些问题        如果说现在有一个接口经过了长年 ...

  8. Java开发笔记(三十六)字符串的常用方法

    不管是给字符串赋值,还是对字符串格式化,都属于往字符串填充内容,一旦内容填充完毕,则需开展进一步的处理.譬如一段Word文本,常见的加工操作就有查找.替换.追加.截取等等,按照字符串的处理结果异同,可 ...

  9. Java从零开始学三十八(JAVA IO- 重定向IO)

    一.三个静态变量 java.lang.System提供了三个静态变量 System.in(默认键盘) System.out(默认显示器) System.err 二.重写向方法 System提供了三个重 ...

随机推荐

  1. VUE自学日志01-MVC和MVVM

    一.需要了解的基础概念 Model(M)是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,主要围绕数据库系统展开.这里的难点主要在于需要和前端约定统一的接口规则. View(V)是视图层,也就是 ...

  2. 关于zimbra的复现以及突破

    Zimbra未登录RCE漏洞利用 首先我是根据这个PDF进行复现的,但是复现过程出现很多问题 首先使用这个XXE读取文件 <!DOCTYPE xxe [ <!ELEMENT name AN ...

  3. ES6箭头函数(箭头函数和普通函数的区别)

    箭头函数 一个参数 // 只有一个参数 // f : 函数名称 // v : 函数参数 // v+v : 函数内容 let f=v=> v+v console.log(f(10)) //20 两 ...

  4. 10.8 location

    创建一个前台站点 server { listen 80; server_name www.nginx.com; locaiton / { root /var/www/html/www; } } 创建一 ...

  5. SONiC架构分析

    目录 系统架构 设计原则 核心组件 SWSS 容器 syncd 容器 网络应用容器 内部通信模型 SubscriberStateTable NotificationProducer/Consumer ...

  6. 将DataFrame赋值为可变变量在spark中多次赋值后运行速度减慢的问题

    该问题先标记上,之后有空了研究原因. 在var dataframe后将dataframe作为参数输入某方法,将结果重新赋予该dataframe,会导致spark运行显著减慢速度.暂时不知道原因,之后研 ...

  7. 关于tkinter

    tkinter介绍 tkinter是python自带的GUI库,是对图形库TK的封装tkinter是一个跨平台的GUI库,开发的程序可以在win,linux或者mac下运行 组件概念 一个窗口中任意内 ...

  8. Java:ConcurrentHashMap类小记-3(JDK8)

    Java:ConcurrentHashMap类小记-3(JDK8) 结构说明 // 所有数据都存在table中, 只有当第一次插入时才会被加载,扩容时总是以2的倍数进行 transient volat ...

  9. 第2次 Beta Scrum Meeting

    本次会议为Beta阶段第2次Scrum Meeting会议 会议概要 会议时间:2021年5月31日 会议地点:「腾讯会议」线上进行 会议时长:0.5小时 会议内容简介:对完成工作进行阶段性汇报:对下 ...

  10. Seata的一些概念

    Seata的一些概念 一.什么是seata 二.AT模式的介绍 1.前提条件 2.整体机制 3.读写隔离的实现 1.写隔离 2.读隔离 三.事务分组 1.事务分组是什么? 2.通过事务分组如何找到后端 ...