专栏首页Java患者从面向过程出发到函数式编程(下篇)

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

小编

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

前言

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

函数式接口

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

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

Function接口

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

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

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对象:

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接口中包含一个抽象方法,用在条件判断的场景中,下面我们以一个判断字符串长度为例:

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为例子:

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的方法一样。

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表达式需要“对外提供”一个符合泛型类型的对象数据:

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)用于消费一个指定泛型的数据,基本使用如下

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接口:

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

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

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

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

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

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

// 1到10挑选偶数,扩大2倍values.stream().filter(value -> value%2==0).map(value -> value*2);

小结

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

本文分享自微信公众号 - Java患者(gh_3a16ffdedb6a),作者:茶谪仙

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

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

    java8为我们引入的Lambda表达式、Stream ApI以及方法引用,它们为了java提供函数式编程的支持,虽然目前JDK已经出现到14的版本了,但是小编...

    用户7386338
  • Python编程的三种方式:面向过程、面向函数和面向对象!你会几个?

    点击链接加入群【python┮】:https://jq.qq.com/?_wv=1027&k=5xP1Cuy

    云飞
  • 致开发人员:沉迷面向对象编程不可自拔?函数式编程了解一下

    函数式编程已经存在了60多年,但只有像Google这样的改变游戏规则的企业才会依赖函数式编程,普通程序员对此几乎一无所知。

    IT大咖说
  • 从面向对象到函数式编程: 我们正在构建更成熟的关注点隔离生态系统

    2016.11.17, 深圳, Ken Fang 在谈论关注点隔离生态系统前, 我想,首先需要谈谈 Procedure Programming, Functio...

    Ken Fang 方俊贤
  • 循环、分支...都可以在Python中用函数实现! | 函数式编程,打开另一个世界的大门

    编程界有一位传奇人物——王垠,介绍一下他的退学经历,对,你没听错,退!学!经!历!: 2006年,从清华大学计算机系退学,在水木社区BLOG上发表了《清华梦的...

    数说君
  • C语言嵌入式系统编程修炼之软件架构篇

    这是我13年前创作和发表在互联网上的文章,这么多年过去了,这篇文章仍然在到处传播。现在贴回Linuxer公众号。 全文目录: C语言嵌入式系统编程修炼之道——背...

    企鹅号小编
  • [Python从零到壹] 三.语法基础之文件操作、CSV文件读写及面向对象

    欢迎大家来到“Python从零到壹”,在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界。所有文章都将结合案例...

    Eastmount
  • php面试中关于面向对象的相关问题

    PHP中面向对象常考的知识点有以下7点,我将会从以下几点进行详细介绍说明,帮助你更好的应对PHP面试常考的面向对象相关的知识点和考题。

    砸漏
  • 来自Kenneth Reitz大神的建议:避免不必要的面向对象编程

    你也许见过很多人对于Python的评价,他们说Python是“脚本语言”和“胶水语言”,在某种程度上,他们说的是对的。但是,如果你学习过Python,你会知道P...

    Python猫
  • Java基础类第一批书籍推荐

    本书是Java语言的经典教材,中文版分为基础篇和进阶篇,主要介绍程序设计基础、面向对象程序设计、GUI程序设计、数据结构和算法、高级Java程序设计等内容.本书...

    用户5224393
  • 一文读懂高性能网络编程中的I/O模型

    随着互联网的发展,面对海量用户高并发业务,传统的阻塞式的服务端架构模式已经无能为力。本文(和下篇《高性能网络编程(六):一文读懂高性能网络编程中的线程模型》)旨...

    JackJiang
  • 一文读懂高性能网络编程中的I/O模型

    随着互联网的发展,面对海量用户高并发业务,传统的阻塞式的服务端架构模式已经无能为力。本文(和下篇《高性能网络编程(六):一文读懂高性能网络编程中的线程模型》)旨...

    JackJiang
  • Elixir和OTP中面向过程的编程指南

    这篇文章感觉介绍语言是次,讲解各种各种分类以及面向过程的思想为主。本身我也没接触过Elixir,这次也权当开拓视野了。最后附加了一个英语单词的小解,当学习之余的...

    WindCoder
  • FPGA 之 SOPC 系列(五)Nios II 软件使用与程序开发 I

    今天给大侠带来今天带来FPGA 之 SOPC 系列第五篇,Nios II软件使用与程序开发 I,希望对各位大侠的学习有参考价值,话不多说,上货。

    FPGA技术江湖
  • C语言嵌入式系统编程修炼之键盘操作

    这是我13年前创作和发表在互联网上的文章,这么多年过去了,这篇文章仍然在到处传播。现在贴回Linuxer公众号。 全文目录: C语言嵌入式系统编程修炼之道——背...

    企鹅号小编
  • Erlang 入坑指南

    想了半天憋出这么个题目来,这也的确只是一篇入坑文。之前程序君写过一篇 Erlang 文章,我用谷歌翻译出来给 Joe Armstrong 老爷子看,老爷子看后大...

    tyrchen
  • Erlang语言导文

    从业很多年,对于语言其实并没有什么偏执,工作需要什么语言就用什么语言。大家用的最多的可能是C/C++语言,毕竟是算竞的主流,也有很多同学使用Java或者pyth...

    ACM算法日常
  • 如何编写高质量的 JS 函数(4) --函数式编程[实战篇]

    本文会从如何用函数式编程思想编写高质量的函数、分析源码里面的技巧,以及实际工作中如何编写,来展示如何打通你的任督二脉。话不多说,下面就开始实战吧。

    2020labs小助手
  • C+实现神经网络之三—神经网络的训练和测试

    前言 在之前的博客中我们已经实现了Net类的设计和前向传播和反向传播的过程。可以说神经网络的核心的部分已经完成。接下来就是应用层面了。要想利用神经网络解决实际的...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券