java Function接口实践

本文介绍了Java 1.8引入的Function接口,用于函数式编程。Function接口表示接受一个参数并返回一个结果的函数,提供了apply、andThen、compose和identity等方法。apply是核心方法,andThen和compose用于组合函数,identity则返回一个始终返回原参数的Function对象。在编程中,应优先考虑使用标准函数接口,以提高代码可读性和复用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、简介

1.1、作用

该接口自1.8被引入,存在于java.util.function包中,用于配合lambda表达式,完成函数式编程的需求。该接口表示一个函数,它接受一个参数,并返回一个结果,就像 fn(T)=R。

1.2、接口签名

    @FunctionalInterface
    public interface Function<T, R> {...}

其中:

  • <T> 表示函数入参参数类型。
  • <R> 表示函数输出参数类型。

2、常用方法

Function接口,由以下四个方法组成。

2.1、apply

  1. 方法签名:R apply(T t);
  2. 方法说明:apply方法是接口中的抽象方法,接收T类型参数,返回R类型结果。在Function接口中,apply方法是便是lambda表达式的抽象。

示例:
(1).简单示例:输入一个整数,除2后将其返回。

import java.util.function.Function; 

public class Main { 
   public static void main(String args[]) 
   { 
       Function<Integer, Double> half = a -> a / 2.0; 
       System.out.println(half.apply(10)); 
   } 
}

输出:
5.0

(2).简单示例:输入Object对象,执行其toString()并返回。

import java.util.function.Function; 

public class Main { 

 public static void main(String[] args) {
       Function function = s -> s.toString();
       System.out.println(function.apply("hello"));
       System.out.println(function.apply(12345));
   }
}

输出:
hello
12345

在第二个示例中,声明Function时,并未指定类型,所以apply可以接收任何Object对象,并且执行其toString(),然后返回。

2.2、addThen

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

如上,andThen是一个默认实现方法,它接收一个Function类型的参数after,并且需要确保after不能为空,否则将向上抛出NPE,然后是一段lambda表达式所表示的Function。lambda表达式体中,只有一句代码:after.apply(apply(t)),主要的作用是在执行完this.apply后,再执行after.apply,所以最后返回的结果是一对组合函数。

示例:
(3) 简单示例:在简单示例(2)的基础上,添加andThen。

import java.util.function.Function; 

public class Main { 

public static void main(String[] args) {

       Function function = s -> s.toString();
       function = function.andThen(a -> a + " ---> after");
       
       System.out.println(function.apply("hello"));
       System.out.println(function.apply(12345));
   }
}

输出:
hello ---> after
12345 ---> after

2.3、compose

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

compose与andThen类似,不同的是compose是在执行this.apply()之前执行before.apply(),最后返回一组组合函数。

示例
(4)简单示例:在简单示例(3)的基础上添加compose。

import java.util.function.Function; 

public class Main { 

    public static void main(String[] args) {
        Function function = s -> s.toString();
	    function = function.andThen(a -> a + " ---> after");
	    function = function.compose(a -> "compose -- > " + a);
	
	    System.out.println(function.apply("hello"));
	    System.out.println(function.apply(12345));
    }
	 
}

输出:
compose -- > hello ---> after
compose -- > 12345 ---> after

2.4、identity

  1. 源码
static <T> Function<T, T> identity() {
    return t -> t;
}
  1. 源码分析

identity()方法是一个静态方法,不接收任何参数,返回一个Function<T,T>对象(Function<T,T> 表示apply()方法的入参类型与出参类型一致)。此Function对象的作用可以用fn(x) = x表示,也就是在执行apply(x)时,原样返回x。

示例
(5)简单示例:identity示例。

import java.util.function.Function; 

public class Main { 

    public static void main(String[] args) {
        Function<String, String> f = Function.identity();
        Function<String, String> f1 = Function.identity();
        System.out.println(f1.apply("identity demo ~"));

        Function f2 = Function.identity();
        System.out.println(f2.apply("identity demo ~"));
        Date now = (Date) f2.apply(new Date());
        System.out.println(now);
    }
	 
}

输出:
identity demo ~
identity demo ~
Sat Aug 10 12:34:28 CST 2019

在上面示例中,f2没有指定Function泛型类型,默认为Function<T,T>,所以在将f2.apply(new Date())赋值给now时,需求强制转换为Date对象。

3、小结

本篇介绍了Function的作用与四个方法,其中apply方法是需要我们去实现,一般我们会用lambda表示。addThen()方法和compose()方法是默认方法,分别与apply方法组成一对组合函数,addThen()在apply()之后执行,compose()方法在apply()之前执行。identity()方法返回一个类似于fn(x) = x的Function。

在编程过程中,如果你有类似于下面这种接口:

@FunctionalInterface
public interface Foo {
    String method(String string);
}

你应该要优先考虑使用标准函数接口:Function,而不是自己再去定义。
同时java.util.function包中还有许多常见的函数接口,如BiConsumer、BiFunction等,在自己编写函数接口时,可以先去此包下探索一番再来考虑是否要自己编写。

参考

  1. https://www.baeldung.com/java-8-lambda-expressions-tips
  2. https://www.geeksforgeeks.org/function-interface-in-java-with-examples
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值