前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从面向过程出发到函数式编程(下篇)

从面向过程出发到函数式编程(下篇)

作者头像
用户7386338
发布2020-05-31 10:04:50
3350
发布2020-05-31 10:04:50
举报
文章被收录于专栏:Java患者

小编

专注分享Java技术,坚持原创,你的关注和转发就是我们最好的动力。

前言

在上一个章节我们讲到Java程序的函数式编程是如何发展的而来的,那么本篇我们来说下Java为函数式编程提供哪些便利的地方。

函数式接口

我们知道,方法引用和Lambda表达式使用的时候,只需要知道我们的方法签名就行,而不在乎我们的接口名字。那么java的函数式接口真是为了避免我们每次使用需要自己去创建接口而提供的。

java提供的是函数式接口位于java.util.function.*路径下面,这些接口代表了接口调用的各种不同应用场景。

Function接口

Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。

Function 接口中最主要的抽象方法为:R apply(T t) ,根据类型T的参数获取类型R的结果。下面我们将 String 类型转换为 Integer 类型:

代码语言:javascript
复制
public class Demo11FunctionApply {    private static void method(Function<String, Integer> function) {        int num = function.apply("10");        System.out.println(num + 20);    }
    public static void main(String[] args) {        method(s ‐ > Integer.parseInt(s));    }}

Function 接口中有一个默认的 andThen 方法,该方法同样用于“先做什么,再做什么”的场景。下面我们来看一个例子,把传入的String字符串转成int类型,做加法操作后,把结果交给第二个Function对象:

代码语言:javascript
复制
public class Demo12FunctionAndThen {    private static void method(Function<String, Integer> one, Function<Integer, Integer> two) {        int num = one.andThen(two).apply("10");        System.out.println(num + 20);    }
    public static void main(String[] args) {        method(str‐ > Integer.parseInt(str) + 10, i ‐>i *= 10);    }}

Predicate接口

如果我们需要对某种数据类型进行判断,从而得到一个Boolean值结果。那么我们就可以使用到Predicate接口。

boolean test(T t)是Predicate接口中包含一个抽象方法,用在条件判断的场景中,下面我们以一个判断字符串长度为例:

代码语言:javascript
复制
private static void method(Predicate<String> predicate) {    boolean veryLong = predicate.test("HelloWorld");    System.out.println("你的字符串是否超出5位字符:" + veryLong);}
public static void main(String[] args) {    method(s -> s.length() > 5);}

Predicate接口有一个andor的默认方法,用于做与和或的判断逻辑,我们以一个判断一个字符串长度既要大于5,又要小于10为例子:

代码语言:javascript
复制
private static void method(Predicate<String> one, Predicate<String> two) {    boolean isValid = one.and(two).test("Helloworld");    System.out.println("字符串符合要求吗:" + isValid);}public static void main(String[] args) {    method(str -> str.length()>5, str -> str.length()<6);}

“非”的逻辑关系的默认方法是negate。JDK源码中是将test方法返回值进行取反,所以一定要在test方法调用之前调用negate方法,正如and和or的方法一样。

代码语言:javascript
复制
private static void method(Predicate<String> predicate) {    boolean veryLong = predicate.negate().test("HelloWorld");    System.out.println("你的字符串不是超出5位字符:" + veryLong);}
public static void main(String[] args) {    method(s -> s.length() > 5);}

Supplier接口

Supplier接口用来获取一个泛型参数指定类型的对象数据,作为一个生成接口,他需要对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据:

代码语言:javascript
复制
private static String getString(Supplier<String> function) {    return function.get();}public static void main(String[] args) {    String msgA = "Hello";    String msgB = "World";    System.out.println(getString(() -> msgA +msgB));}

Consumer接口

Consumer<T> 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,void accept(T t)用于消费一个指定泛型的数据,基本使用如下

代码语言:javascript
复制
private static void consumeString(Consumer<String> function) {    function.accept("Hello");}public static void main(String[] args) {    consumeString(s ‐ > System.out.println(s));}

结合Stream API的时候

Stream API的reduce()使用到Function接口:

代码语言:javascript
复制
// 从1到10累计并且把计算结果打印List<Integer> values = range(1,10);Integer result = values.stream().reduce(0, Integer::sum);

Stream API的forEach()使用到Consumer接口:

代码语言:javascript
复制
// 将1-10全部打印// Consumer接口,只接收数据不返回values.stream().forEach(System.out::println);

Stream API的filter()使用到Predicate接口:

代码语言:javascript
复制
// 1到10挑选偶数,打印累计的值values.stream().filter(value -> value%2==0).reduce(0,Integer::sum);

Stream API的map()使用到Function接口:

代码语言:javascript
复制
// 1到10挑选偶数,扩大2倍values.stream().filter(value -> value%2==0).map(value -> value*2);

小结

  • Consumer:只接受数据,不返回(消费者)
  • Supplier:没有接收数据,只有返回(提供数据,生产者)
  • Predicate:判断(1-10挑选偶数)
  • Function:转换(Integer -> Integer*2)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java患者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档