Java中的函数式编程

🥂 Java中的函数式编程

面向对象编程思想和函数编程思想

通过面向对象设计一个程序

有这样的一个需求,需要设计一个 程序员使用字符处理器来处理文本的程序.
根据面向对象的设计思想,我们需要设计这样两个类.

  1. 程序员类
  2. 字符处理器类

考虑到可能用到不同的字符处理器,所以设计一个字符处理器接口,不同的字符处理器继承该接口以供程序员在不同的业务场景下使用.
得到的类图如下:
在这里插入图片描述

实现上述代码:
创建一个 Programmer程序员类,提供了工作的方法,该方法可以使用 字符处理器来处理一个字符
定义一个 StringProcessor字符处理器接口,他提供一个 apply方法
创建一个 AppendStringProcessor类, 继承 StringProcessor实现 append方法

/**程序员*/
public class Programmer{
    /**工作方法,通过使用字符处理器的apply()方法处理字符*/
	public String work(StringProcessor sp,String str){
    	retrun sp.apply(str);
    }
}
/**字符处理器*/  
public interface StringProcessor{
    String apply(String str);
}
/** 对字符增加前缀的处理器 */  
public class  AppendStringProcessor implements StringProcessor{
  @Override
  String append(String str){
     return "斯密" + str;
  }
}

面向对象的语言强调,万物皆对象,我们必须通过调用合适的对象合适的方法来完成一件事,所以该程序运行过程为
创建程序员对象
创建字符处理器对象
在程序员的work方法中,我们调用了字符处理器的apply 方法 完成了对字符的处理

//程序员对象
Programer programer = new Programer();
//字符处理器对象
StringProcessor stringProcessor = new AppedStringProcessor();
//调用对象的方法
String result = programer.work(stringProcessor,"马赛");

上述代码是通过面向对象的思想来完成的,我们通过字符处理器类,创建字符处理器对象,调用该对象的方法来完成编码,但是抛开面向对象,我需要的只是处理字符串的行为,也就是实现类方法体部分,并不需要字符处理器的对象
lambda 解决的就是在一些情况下,面向对象代码的笨重和不灵活.他可以让我们关注于方法,而不需要创建并使用一个拥有该方法的对象.


接下来对代码进行改造,一步步修改为通过** lambda** 完成功能

1. 通过匿名类代替创建 AppendStringProcessor 类
    StringProcessor stringProcessor = new StringProcessor() {
    	@Override
    	public String append(String str) {
    		return "斯密" + str;
     	}
     };

使用匿名类后,便不需要创建实现接口的类

2. 匿名类向lambda进行演变
  1. 去掉多余的部分,只保留 方法参数方法体,参数和 **方法 **之间加上符号 -> .
StringProcessor stringProcessor = (String str) -> {
  	return "斯密" + str ;
};
  1. retrun 和 **{ } **去掉
StringProcessor stringProcessor = (String str) -> "斯密" + str;
  1. 去掉参数类型,当参数只有一个时,还可以把 ( ) 去掉
StringProcessor stringProcessor = str -> "斯密" + str;

这个时候,代码已经由匿名类,演变为 lambda 了.

3. 通过java.util.function提供的函数式接口,代替自己创建 StringProcessor 接口

创建 **StringProcessor **接口是为了 提供一个接受一个 **String **类型的参数,返回一个 **String **类型的结果的方法, **java.util.funciton **包中已经提供的各种各样的函数式接口,可以直接使用.
**java.util.function **包下函数式接口的行为和功能
选择符合条件的函数式接口 java.util.function.Function<T,R>

Function<String,String> stringProcessor = str -> "斯密" + str;

这个时候代码变成了如下

//程序员对象
Programer programer = new Programer();
//调用对象的方法
String result = programer.work(str -> "斯密" + str , "马赛");

函数式编程中函数作为一等公民
第一等公民,指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
把处理字符的方法当参数传递给了 **work **方法,便是函数式编程

函数式编程在开发中用处

ArrayList 是如何使用lambad实现循环的

//调用ArrayList的forEach方法
new ArrayList<>().forEach(ele -> {
    System.out.println(ele);
});
//forEach的源码
public void forEach(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    int expectedModCount = this.modCount;
    Object[] es = this.elementData;
    int size = this.size;

    for(int i = 0; this.modCount == expectedModCount && i < size; ++i) {
        action.accept(elementAt(es, i));
    }
}

forEach( ) 方法中的参数,便是处理集合中元素的方法,这里同样是把方法作为参数传递.
循环集合的目的是为了处理元素,我们只需要把如何处理元素的方法作为参数传递给它,而不是面向对象思想中向它提供一个拥有处理元素方法的对象.这就是函数式编程之所以可以让程序变得简单的原因.

方法引用

方法引用是 lambda 的语法糖.当发生如下情况时

      new ArrayList<String>().forEach(ele -> {
          System.out.println(ele);
      });

在这个函数中,方法体仅仅是调用了另一个方法,那么可以直接使用这个方法来作为参数传递.

        new ArrayList<String>().forEach(System.out::println);

使用了System.out对象的println方法来代替了自己创建函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值