JAVA-Function基础使用

本文介绍了如何在Java8的Function接口及其相关类(如BiFunction和Consumers)中,通过lambda表达式优化代码,减少方法间记录耗时的冗余。作者展示了如何使用这些工具简化方法调用并提高代码可读性。

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

🧾 概述

        在日常开发中,我们经常需要对方法进行耗时统计。传统方式通常是手动在每个方法前后添加计时逻辑,这不仅冗余,还不易维护。本文介绍如何使用 Java 8 函数式接口(如 FunctionBiFunctionConsumer 等)进行封装,使耗时统计更简洁、通用、可复用。

介绍

   Function 接口是 Java 8 引入的函数式接口,简单来说,它可以将一个方法封装成 Function 对象,作为参数传递。Java 8 的 java.util.function 包包含了许多函数式接口,今天我们将简单介绍我常用的四种接口:

  1. Function:接受一个参数并返回一个结果。

  2. BiFunction:接受两个参数并返回一个结果。

  3. Consumer:接受一个参数,但不返回任何结果。

  4. BiConsumer:接受两个参数,但不返回任何结果。

这些接口帮助我们在方法中使用更简洁的方式传递行为,极大地提高了代码的灵活性和可读性。

🧠 传统写法(优化前)

可以看到,每个方法一次记录,那么就代表每个方法调用都需要写至少4行进行使用

    public static void main(String[] args) {
        final Long staTime = System.currentTimeMillis();
        Demo2.test1("方法1");
        final Long endTime = System.currentTimeMillis();
        System.out.println(String.format("方法1耗时%s",endTime - staTime));

        final Long staTime2 = System.currentTimeMillis();
        Demo2.test1("方法2");
        final Long endTime2 = System.currentTimeMillis();
        System.out.println(String.format("方法2耗时%s",endTime2 - staTime2));
    }

缺点:重复代码多,可读性和可维护性差。 

🧩 使用函数式接口进行封装(优化后)

附上一个demo,当前demo中是我封装的上面4个类的方法。

✅ 封装类示例

import java.util.function.*;

/**
 * @author 崔
 * @version 0.0.1
 * @Date 2023/8/15 19:51
 */
public class Demo {


     /**
     * 一个入参有返回值
     *
     * @param functionName    名称
     * @param t        入参
     * @param function 方法
     * @param <R>      返回结果
     * @return R
     */
    public static <T, R> R oneValue(final String functionName,
                             final T t, final Function<T, R> function) {
        final Long staTime = System.currentTimeMillis();
        final R r = function.apply(t);
        final Long endTime = System.currentTimeMillis();
        System.out.println(String.format("方法%s耗时%s",functionName,endTime - staTime));
        return r;
    }

    /**
     * 两个入参一个返回值
     *
     * @param functionName    方法名称
     * @param t        审核入参
     * @param u        通用的service
     * @param function 方法
     * @param <R>      返回结果
     * @return R
     */
    public static <T, U, R> R twoValue(final String functionName,
                                final T t,
                                final U u,
                                final BiFunction<T, U, R> function) {
        final Long staTime = System.currentTimeMillis();
        final R r = function.apply(t, u);
        final Long endTime = System.currentTimeMillis();
        System.out.println(String.format("方法%s耗时%s",functionName,endTime - staTime));
        return r;
    }

    /**
     * 一个入参没有返回值
     *
     * @param functionName
     * @param t
     * @param function
     */
    public static <T> void oneNot(final String functionName,
                           final T t,
                           final Consumer<T> function) {
        final Long staTime = System.currentTimeMillis();
        function.accept(t);
        final Long endTime = System.currentTimeMillis();
        System.out.println(String.format("方法%s耗时%s",functionName,endTime - staTime));
    }

    /**
     * 两个入参没有返回值
     *
     * @param functionName
     * @param t
     * @param u
     * @param function
     * @param <T>
     * @param <U>
     */
    public static <T, U> void twoNot(final String functionName,
                              final T t,
                              final U u,
                              final BiConsumer<T, U> function) {
        final Long staTime = System.currentTimeMillis();
        function.accept(t, u);
        final Long endTime = System.currentTimeMillis();
        System.out.println(String.format("方法%s耗时%s",functionName,endTime - staTime));
    }
}

✨ 使用示例

优化后,代码不但减少,而且更美观。

    public static void main(String[] args) {
        Demo.oneValue("方法1", "入参", Demo2::test1);//一个入参有返回值
        Demo.twoValue("方法2", "入参1", "入参2", Demo2::test2);//两个入参有返回值
        Demo.oneNot("方法1", "入参", Demo2::test3);//一个入参没返回值
        Demo.twoNot("方法2", "入参1", "入参2", Demo2::test4);//两个入参没返回值
    }

🔁 多参数泛用封装(进阶)

描述:无限入参并有返回值

优点:不限制入参数量

确定:入参需要用final修饰

下面看代码示例

✅ 自定义接口 

import java.util.Objects;
import java.util.function.Function;

/**
 * @author 崔
 * @Date:2025/4/25 10:41
 * @vesion: 0.0.1
 */
@FunctionalInterface
public interface ObjFunction<R> {

    R apply(Object... args);

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

}

✅ 泛用方法封装

public <R> R funApply(final String title,//标题
                             final ObjFunction<R> objFunction,//方法
                             final Object... o//方法入参
) {
        final Long staTime = System.currentTimeMillis();
        final R r = objFunction.apply(o);
        final Long endTime = System.currentTimeMillis();
        this.audLogTimeData(title, staTime, endTime);
        return r;
}

✨ 使用示例 

public static void main(String[] args) {
    String result = Demo.funApply("方法2", (args) -> Demo2.test2("入参1", "入参2");//一个入参有返回值
}

✅ 总结

对于Function包中,还有很多其他的方法,比如返回boolean类型的参数,还可以自己封装多个参数的,目前封装好的最多两个入参,多个方法还能配合使用。

### Java 函数定义和用法 #### 定义函数Java中,函数被称为方法,二者表达相同的概念。这些是封装了具备特定功能的一段代码块,有助于解决重复性代码的问题并提高程序的模块化程度[^4]。 一个完整的Java函数定义通常包括以下几个部分: - **访问修饰符**:如`public`, `private`, 或者默认(无关键字) - **返回类型**:指定该函数执行完毕后返回的数据类型 - **函数名**:遵循驼峰命名法则,首字母小写 - **数列表**:括号内声明输变量及其类型 - **异常抛出说明**(如果有的话) 下面展示了一个简单的例子来创建名为`addNumbers`的方法,它接收两个整数作为数,并返回这两个数值相加的结果: ```java public int addNumbers(int a, int b) { return a + b; } ``` 此示例展示了如何通过定义带有具体逻辑的功能单元——即方法,在实际应用中可以被多次调用来完成相似的任务而不必每次都重新编写相同的代码片段[^1]。 #### 使用函数 一旦定义好了某个函数之后就可以在整个项目里任何地方对其进行调用了。只需要按照如下语法格式即可实现这一点: ```java // 假设我们已经在同一个类里面定义过上面提到过的addNumbers() 方法 int sum = addNumbers(3, 7); System.out.println("Sum is " + sum); // 输出 Sum is 10 ``` 这里的关键在于理解当遇到复杂问题时可以通过分解成多个更简单的小任务的方式来处理,每一个这样的子任务都可以由独立编写的函数负责完成。这不仅提高了开发效率还增强了维护性和扩展性的能力[^2]。 另外值得注意的是因为Java是一门完全面向对象的语言所以所有的函数都需要放在类当中去定义,这也意味着即使是最基本的操作也应该视为某一类别下的行为或者说动作[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值