JAVA8之函数式编程Function接口用法

从这章开始,会介绍几个常用的函数式接口工具,首先先来看下这个大家族:

首先从Function接口开始介绍

一. 概述

该接口顾名思义,函数的意思,就像是数学,是给定一个参数然后返回结果.该类方法如下:

package java.util.function;
import java.util.Objects;

@FunctionalInterface
public interface Function<T, R> {

 R apply(T t);

 default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
  Objects.requireNonNull(before);
  return (V v) -> apply(before.apply(v));
 }

 default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
  Objects.requireNonNull(after);
  return (T t) -> after.apply(apply(t));
 }

 static <T> Function<T, T> identity() {
  return t -> t;
 }

1. apply方法

该接口的唯一个抽象类是apply方法,接受一个类型的参数,有返回值.功能是将参数赋予相应的方法.

2. compose方法

默认方法,先用入参去调用apply方法,然后再用调用者去调用apply方法.调用的Object.requireNonNull是java7的新特性,如果before是null值的话直接抛出异常.

3. andThen方法

默认方法,与compose方法相反,先用调用者去调用apply方法,然后再用入参去调用apply方法.

4. identity方法

静态方法,java8新特性,返回当前正在执行的方法.

二. 示例

不难看出,除了第一个方法以外,其他三个方法的返回值都是Function,所以后面三个方法是可以链式调用(即用"."方法)的,就如建造者模式(Build)一样.理论讲完,上代码:

package com.yczuoxin.demo;
import java.util.function.Function;
public class FunctionTest {
 public static void main(String[] args) {
  // 先声明方法
  Function<Integer, Integer> funcDouble = (n) -> n * 2;
  Function<Integer, Integer> funcPlus2 = (n) -> n + 2;

  System.out.println(funcDouble.apply(3));
  System.out.println(funcPlus2.apply(3));

  System.out.println(funcDouble.andThen(funcPlus2).apply(3));
  System.out.println(funcDouble.compose(funcPlus2).apply(3));
  System.out.println(Function.identity().compose(funcDouble).apply(8));
 }
}

运行结果:

把计算过程也写在上面应该就能知道执行顺序了吧.

三. 总结

这个工具类感觉就是回到了学数学的场景,自己规定函数,然后调用函数,其实不仅仅可以调用一次andThen方法,后面还以加,只是没有写出来而已,大家可以自己去尝试一下.

补充知识:JAVA8之函数式编程Predicate接口

一.概述

先上这个接口的源码:

package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Predicate<T> {

 boolean test(T t);

 default Predicate<T> and(Predicate<? super T> other) {
  Objects.requireNonNull(other);
  return (t) -> test(t) && other.test(t);
 }

 default Predicate<T> negate() {
  return (t) -> !test(t);
 }

 default Predicate<T> or(Predicate<? super T> other) {
  Objects.requireNonNull(other);
  return (t) -> test(t) || other.test(t);
 }

 static <T> Predicate<T> isEqual(Object targetRef) {
  return (null == targetRef)
    ? Objects::isNull
    : object -> targetRef.equals(object);
 }
}

1.test方法

该方法是接受一个传入类型,返回一个布尔值.此方法应用于判断.

2.and方法,or方法

该些方法接收的是一个Predicate类型参数,返回的也是一个Predicate类型.and方法用于两个判断是否都成立,与关系型运算符"&&"相似.而or方法则用于两个判断是否有一个成立.与关系型运算符"||"相似.

3.negate方法

该方法没有传入参数,返回一个Predicate类型.此方法用于对判断进行取反.与关系型云算法"!"相似.

4.isEqual方法

该方法接收一个Object对象,返回一个Predicate类型.此方法用于判断第一个test的方法与第二个test方法相同(equal).

二. 示例

写一个判断字符串的一个判断工具类,包含Predicate4种方法,并返回判断结果.

package com.yczuoxin.demo.predicate;
import java.util.function.Predicate;
public class PredicateUtil {
 public static boolean judgeString(String str, Predicate<String> p){
  if(null == str){
   return false;
  }
  return p.test(str);
 }

 public static boolean judgeNoString(String str, Predicate<String> p){
  if(null == str){
   return false;
  }
  return p.negate().test(str);
 }

 public static boolean judgeAndDoubleString(String str, Predicate<String> p1, Predicate<String> p2){
  if(null == str){
   return false;
  }
  return p1.and(p2).test(str);
 }

 public static boolean judgeOrDoubleString(String str, Predicate<String> p1, Predicate<String> p2){
  if(null == str){
   return false;
  }
  return p1.or(p2).test(str);
 }
}

测试字符串长度是否大于4的方法用例:

package com.yczuoxin.demo.predicate;
import java.util.function.Predicate;
public class PredicateTest {
 public static void main(String[] args) {
  String testString = "abcde";
  // 判断字符串长度是否大于4
  System.out.println(PredicateUtil.judgeString(testString,p->p.length()>4));
  // 判断字符串长度是否大于4再取反
  System.out.println(PredicateUtil.judgeNoString(testString,p->p.length()>4));
  // 判断字符串长度是否大于4并且小于8
  System.out.println(PredicateUtil.judgeAndDoubleString(testString,p->p.length()>4,p->p.length()<8));
  // 判断字符串长度是否小于4并且大于8
  System.out.println(PredicateUtil.judgeOrDoubleString(testString,p->p.length()<4,p->p.length()>8));
  // 判断当前方法是否是"test"方法.
  System.out.println(Predicate.isEqual("test").test("test"));
  System.out.println(Predicate.isEqual("test").test("test1"));
 }
}

测试结果:

三. 总结

Predicate适合在工具类和条件筛选的条件下使用,减少if...else的使用,并且使用灵活.

以上这篇JAVA8之函数式编程Function接口用法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • java8学习教程之lambda表达式的使用方法

    前言 我们在 上一篇文章 中介绍了 lambda 表达式的语法,引入了 lambda 表达式的使用场景,以及使用 lambda 表达式的好处.我们将在这篇文章中,已实例讲解如何定义和使用 lambda 表达式,以及与其它语言相比,lambda 表达式在 Java 中的特殊规范. 使用匿名内部类的例子 首先明确一点,在 Java8 出现之前,lambda 表达式能够做到的,使用内部类也能做到,lambda 表达式只是简化了编程. 下面的例子是从列表中根据条件挑选出读者. 定义 TantanitRe

  • Java8中的lambda表达式入门教程

    1.基本介绍 lambda表达式,即带有参数的表达式,为了更清晰地理解lambda表达式,先上代码: 1.1 两种方式的对比 1.1.1 方式1-匿名内部类 class Student{ private String name; private Double score; public Student(String name, Double score) { this.name = name; this.score = score; } public String getName() { ret

  • java8新特性之方法引用示例代码

    简介 方法引用是java8的新特性之一, 可以直接引用已有Java类或对象的方法或构造器.方法引用与lambda表达式结合使用,可以进一步简化代码. 方法引用的使用场景 我们用Lambda表达式来实现匿名方法.但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,在这种情况下,我们倾向于通过方法名来调用它,而Lambda表达式可以帮助我们实现这一要求,它使得Lambda在调用那些已经拥有方法名的方法的代码更简洁.更容易理解.方法引用可以理解为

  • JAVA8之函数式编程Function接口用法

    从这章开始,会介绍几个常用的函数式接口工具,首先先来看下这个大家族: 首先从Function接口开始介绍 一. 概述 该接口顾名思义,函数的意思,就像是数学,是给定一个参数然后返回结果.该类方法如下: package java.util.function; import java.util.Objects; @FunctionalInterface public interface Function<T, R> { R apply(T t); default <V> Functio

  • 浅析Java8的函数式编程

    前言 本系列博客,介绍的是JDK8 的函数式编程,那么第一个问题就出现了,为什么要出现JDK8?   JAVA不是已经很好,很强大了吗,很多公司用的还是1.6,1.7呀,1.8有必要吗?更不要提即将问世的JDK9了,鲁迅的<拿来主义>说过这么一句话   JAVA如果真的这么完美无缺,那为什么还会有其他语言的兴盛呢?所以说,没有一样东西是绝对完美的,JDK8包括之后的版本,就是不断的完善JAVA语言,让它往更好的方向上去走,面向过程有它的缺点,然而无疑也有它的优点,在JAVA8 之前,JAVA欠

  • Java8新特性:函数式编程

    首先需要清楚一个概念:函数式接口:它指的是有且只有一个未实现的方法的接口,一般通过FunctionalInterface这个注解来表明某个接口是一个函数式接口.函数式接口是Java支持函数式编程的基础. 1 Java8函数式编程语法入门 Java8中函数式编程语法能够精简代码. 使用Consumer作为示例,它是一个函数式接口,包含一个抽象方法accept,这个方法只有输入而无输出. 现在我们要定义一个Consumer对象,传统的方式是这样定义的: Consumer c = new Consum

  • Python函数式编程指南(二):从函数开始

    2. 从函数开始 2.1. 定义一个函数 如下定义了一个求和函数: 复制代码 代码如下: def add(x, y):     return x + y 关于参数和返回值的语法细节可以参考其他文档,这里就略过了. 使用lambda可以定义简单的单行匿名函数.lambda的语法是: 复制代码 代码如下: lambda args: expression 参数(args)的语法与普通函数一样,同时表达式(expression)的值就是匿名函数调用的返回值:而lambda表达式返回这个匿名函数.如果我们

  • Java8之函数式接口及常用函数式接口讲解

    目录 函数式接口 1.概念 2.@FunctionalInterface 3.函数式接口使用方式 常用函数式接口 1.JDK提供的函数式接口举栗 2.Supplier 3.Consumer 4.Predicate 5.Function 6.常用函数式接口相关扩展接口 函数式接口 1.概念 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口. 函数式接口可以被隐式转换为 lambda 表达式. Lambda 表达式和方法引用(实际上也

  • 深入浅出讲解Java8函数式编程

    目录 什么是函数式编程 Java8内置了一些常用的方法接口FunctionalInterface 用的比较多的函数接口 总结 什么是函数式编程 函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用.而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的. 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还

  • JavaScript函数式编程(Functional Programming)高阶函数(Higher order functions)用法分析

    本文实例讲述了JavaScript函数式编程(Functional Programming)高阶函数(Higher order functions)用法.分享给大家供大家参考,具体如下: 高阶函数(higher-order functions),就是返回其它函数的函数,或者使用其它函数作为它的参数的函数. 使用函数作为参数 因为函数本身就是一个值,所以可以让函数作为参数传递给其它的函数.JavaScript 有些函数就需要用到函数类型的参数,比如 Array.map. 比如我有一组数据: con

  • 妙用Java8中的Function接口消灭if...else

    目录 Function 函数式接口 Supplier供给型函数 Consumer消费型函数 Runnable无参无返回型函数 使用小技巧 处理抛出异常的if 处理if分支操作 如果存在值执行消费操作,否则执行基于空的操作 结尾 在开发过程中经常会使用if...else...进行判断抛出异常.分支处理等操作.这些if...else...充斥在代码中严重影响了代码代码的美观,这时我们可以利用Java 8的Function接口来消灭if...else.... if (...){ throw new R

  • Java8深入学习系列(二)函数式编程

    前言 在之前的一篇文章中我们快速学习了lambda和Stream,本章节中我们来回顾和理解函数式编程的思想. 我们不断的提及函数式这个名词,它指的是lambda吗?如果是这样,采用函数式编程能为你带来什么好处呢? 函数式的思考 命令式编程 一般我们实现一个系统有两种思考方式,一种专注于如何实现,比如下厨做菜,通常按照自己熟悉的烹饪方法:首先洗菜, 然后切菜,热油,下菜,然后-- 这看起来像是一系列的命令合集.对于这种"如何做"式的编程风格我们称之为命令式编程, 它的特点非常像工厂的流水

  • JavaScript函数式编程(Functional Programming)组合函数(Composition)用法分析

    本文实例讲述了JavaScript函数式编程(Functional Programming)组合函数(Composition)用法.分享给大家供大家参考,具体如下: 组合(Composition)函数,就是把两个或以上的函数组合到一块儿,整成一个新的函数.我找到了一个很好的例子,很好地解释了组合函数这个概念. 比如一个应用主要是记录一下日常的花销(expenses),应用里的数据看起来像这样: const expenses = [ { name: '租金', price: 3000, type:

随机推荐