初识java中的函数式编程(以Stream类的reduce、collect方法为例)

简介

最近看到别人写的项目中有看不太懂的东西,于是就单独学习了一哈,拿出来记录一下。

本文以java.util.stream类的reduce(T identity, BinaryOperator accumulator)方法和collect(Collector collector)方法为例子讲述函数式编程是个啥,有啥用。

函数式编程

函数式接口的定义:指(只拥有一个未实现的方法的)接口
例子:

Consumer c = o -> System.out.println(o);
c.apply("hello,world~")

这个例子中,等号左边的Consumer是一个函数式接口,内含一个未实现的void apply(T t)方法(见源码),而等号右边的函数则是对这个apply方法的实现。

当然,比较常见的用处并不是用等号直接将实现函数赋值给函数式接口,而是将实现函数以参数传递给所需要这个接口的方法中去,见例1。

直观上可看出来的好处:一个函数式接口的实质也就是个函数,函数式接口可以配合lambda表达式作为参数传递到各个方法内,即一些代码段可以作为参数传递到函数内部去,直观的可以感觉出来这样是挺简洁的,感觉可以共用一些代码段,然后自己再自定义一些代码段,从而少写点代码~

例1:T reduce(T identity, BinaryOperator accumulator)

stream流是一个用于处理集合的类,内置了很多有用的方法如reduce、collect来对流中的数据进行处理,其中reduce()接口重载了3种方法,其中含有2个参数的方法reduce(T identity, BinaryOperator accumulator)的内部实现主要为:

  T result = identity;
  for(T item : this stream) 
  	result = accumulator.apply(result,item)
  return result;

由以上源码可看出,reduce实质上就是一个对传入集合流的迭代操作器~

传入的函数式接口即函数也就是继承了BiConsumer接口的BinaryOperator接口的apply方法,其定义如下:

T apply(T result, T item);
/**
注:
* 原BiConsumer接口中的apply的定义为:R apply(T t, U u) ~~~
* 第一个参数对应reduce中的result,第二个参数对应reduce中的item
* item项即为list.stream().reduce(.....)中的list中的每一项
*/

reduce的参数BinaryOperator accumulator作为一个函数式接口,需要传入个重写了apply(result,item)的函数实现之,当然也可以使用lambda表达式。

其中,BinaryOperator 接口继承了BiConsumer<T,T,T>接口【自然继承了其apply(T,T)方法,见源码】,这个BinaryOperator的作用也就是将BiConsumer<T,U,R>变为了BiConsumer<T,T,T>并再添加了2个新方法~(见源码)

例:需要计算1-3的和

//用Arrays.asList(1,2,3)来快速生成一个List,用list.stream()将这个list转为stream() [注:这一步并不是直接引用原list的地址]
int sum = Arrays.asList(1,2,3).stream().reduce(0,(result,item)->(result+item))
System.out.println("sum(1-3) = "+sum)

例2: collect(Collector collector)

源码看不太懂,举个例子来表达它的作用吧:

例子:已有Set<Map.Entry<Integer, String>> s,可将其转化为一个Map<String, String>,过程如下:

  Map<Integer,String> map = new HashMap<>();
        map.put(1,"N1");
        map.put(2,"N2");
        Set<Map.Entry<Integer, String>> s = map.entrySet();
        Map<String,String> m2 = s.stream().collect(Collectors.toMap(e -> String.valueOf(e.getKey()), Map.Entry::getValue));
        System.out.println("after convert,m = "+m2);

其中Collectors.toMap方法中的Function中的apply(T ele)中的ele指的是传入的Set s的每一个T类型的元素

另:

  1. 双冒号简写lambda函数~ 如:person->person.getName() 等价于 Person::getName()
  2. Java提供了3个函数式接口:Consumer、Function、Predicate,而在Java中Stream类、Optional类都封装了许多方法,这些方法都用到了函数式接口。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值