函数式方法的实现(JDK8+)

1、使用场景

例:在业务中难免会有对象嵌套的情况,下面就是模拟对象属性嵌套对象的一个简单Demo,在真实场景中,肯定会有复杂嵌套。我就以下面简单的Demo为例,来讲述函数式方法的实现。

在methodA()和methodB()两个方法中存在着相同的校验,而且最终对目标的处理逻辑却不同,此时按照常规的解决办法肯定是将两个方法中相同的校验部分提取成公共的方法,然后在两个方法中在进行调用,若经过的了校验才在每个方法中执行各自不同的逻辑。

但是,这里有一个问题,若提取了公共校验方法并接受A的对象为参数,那么在校验方法中肯定是需要一层一层的解出来嵌套的对象E并进行校验。然后在methodA()和methodB()方法中肯定会先调用校验方法并传递对象a,经过校验之后再对对象E的属性进行操作。此时问题来了,此时在methodA()和methodB()方法中是没有对A对象进行一层一层的解出来E对象的,所以也就是说当经过校验之后,还需要在各自的方法里在进行一次解剖的操作,此时不就代码不又重复了吗?你可能会想,下面这个直接使用a.getB().getC().getD().getE()一行代码不就拿到了E对象了吗?在下面这个Demo中是这样的,但是若嵌套的对象中包含集合和单实例对象混合呢或者其他更加复杂的嵌套呢,这样的话一行就解决不了了。于是,在这个场景下,我们应该使用公共的函数式方法,也就是将methodA()和methodB()两个方法中各自的处理逻辑提取成一个函数式接口作为公共方法的参数传递,这样的话解剖的过程被提取出来了,然后具体的处理逻辑也以调用处传递的匿名内部类的处理逻辑为准,于是就解决了这个问题,并提高了复用性。

java 复制代码
@Slf4j
public class Test1 {
    public static void main(String[] args) {
        methodA();
        methodB();
    }

    private static void methodA() {
        A a = new A(new B(new C(new D(new E("Y", 24)))));
        B b = a.getB();
        if (b == null){
            return;
        }
        C c = b.getC();
        if (c == null){
            return;
        }
        D d = c.getD();
        if (d == null){
            return;
        }
        E e = d.getE();
        if (e == null){
            return;
        }
        if ("Y".equals(e.getName())){
            e.setAge(20);
        }
        log.info("methodA方法:" + e);
    }

    private static void methodB() {
        A a = new A(new B(new C(new D(new E("Y", 18)))));
        B b = a.getB();
        if (b == null){
            return;
        }
        C c = b.getC();
        if (c == null){
            return;
        }
        D d = c.getD();
        if (d == null){
            return;
        }
        E e = d.getE();
        if (e == null){
            return;
        }
        processString(a, e -> {
            if (18 == e.getAge()){
                e.setName("N");
            }
        });
        log.info("methodB方法:" + e);
    }
}

@Data
@AllArgsConstructor
class A{
    private B b;
}

@Data
@AllArgsConstructor
class B{
    private C c;
}

@Data
@AllArgsConstructor
class C{
    private D d;
}

@Data
@AllArgsConstructor
class D{
    private E e;
}

@Data
@AllArgsConstructor
class E{
    private String name;
    private Integer age;
}

2、结合 java.util.function 包下的Consumer接口实现函数式方法

Java 在 java.util.function 包中提供了许多内置的函数式接口,**Consumer就是其中一个,它接受一个输入参数,然后无返回结果。上述Demo即可结合Consumer**实现函数式方法的提取。

在下面的代码中实现了一个processString方法,该方法接收两个参数,第一个参数是A对象,第二个参数是Consumer 接口。泛型的类型是在processString方法中最终要对谁进行处理,也就是 accept接口的入参类型,然后在methodA()和methodB()方法中通过匿名内部类的方式传递需要处理的逻辑。

java 复制代码
@Slf4j
public class Test1 {
    public static void main(String[] args) {
        methodA();
        methodB();
    }

    private static void methodA() {
        A a = new A(new B(new C(new D(new E("Y", 18)))));
        processString(a, e -> {
            if ("Y".equals(e.getName())){
                e.setAge(20);
            }
        });
        log.info("methodA方法:" + a.getB().getC().getD().getE());
    }

    private static void methodB() {
        A a = new A(new B(new C(new D(new E("Y", 18)))));
        processString(a, e -> {
            if (18 == e.getAge()){
                e.setName("N");
            }
        });
        log.info("methodB方法:" + a.getB().getC().getD().getE());
    }

    private static void processString(A a, Consumer<E> strProcessor) {
        B b = a.getB();
        if (b == null){
            return;
        }
        C c = b.getC();
        if (c == null){
            return;
        }
        D d = c.getD();
        if (d == null){
            return;
        }
        E e = d.getE();
        if (e == null){
            return;
        }
        // 执行接收到的不同处理逻辑
        strProcessor.accept(e);
    }
}

3、java.util.function 包中其他的函数式接口

  • Function<T,R>: 接受一个输入参数,返回一个结果
  • Predicate: 接受一个输入参数,返回布尔值
  • Consumer: 接受一个输入参数,无返回结果
  • Supplier: 无输入参数,返回一个结果
  • BiFunction<T,U,R>: 接受两个输入参数,返回一个结果

还在测试中。。。详细使用会在后续更新!

文章内容若存在错误或需改进的地方,欢迎大家指正!非常感谢!

相关推荐
阿俊-全栈开发3 小时前
LikeShop 多商户 Java 版商城微服务模块拆分与部署架构演进实践
java·微服务·架构·likeshop开源商城·多商户源码
Wang's Blog4 小时前
Java 项目实战:交友项目 - 联系人列表
java·开发语言·交友
我命由我123454 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
叼烟扛炮4 小时前
[LangChain] 学习笔记(02):LCEL 链式调用与动态模型配置实战
服务器·开发语言·网络·笔记·学习·langchain
香蕉大香蕉(06敬畏市场)4 小时前
MySQL 单点详解(01)
java·数据库·mysql·面试·博客·实习
LaughingZhu5 小时前
Product Hunt 热榜 2026-10-30:Empacer、Scape、Floot in ChatGPT
java·前端·数据库·人工智能·chatgpt·notion
未来之窗软件服务5 小时前
Linux 运维日志删除的多种方式—东方仙盟
linux·运维·服务器·仙盟创梦ide·东方仙盟
niucloud-admin5 小时前
NIUCLOUD PHP SAAS上门家政使用文档:服务保障
java·开发语言·php
小雉系统5 小时前
BcoreOS实战:用一个升级包,让Rocky Linux跑进Debian服务器
linux·运维·服务器·debian
IT枫斗者枫哥5 小时前
CompletableFuture失败后返回空列表:异常没了,业务含义也变了
java·后端