函数式方法的实现(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<T>就是其中一个,它接受一个输入参数,然后无返回结果。上述Demo即可结合Consumer<T>**实现函数式方法的提取。

在下面的代码中实现了一个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<T>: 接受一个输入参数,返回布尔值
  • Consumer<T>: 接受一个输入参数,无返回结果
  • Supplier<T>: 无输入参数,返回一个结果
  • BiFunction<T,U,R>: 接受两个输入参数,返回一个结果

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

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

相关推荐
cike_y5 分钟前
Java反序列化漏洞-Shiro721流程分析
java·反序列化·shiro框架
小贾要学习13 分钟前
【Linux】TCP网络通信编程
linux·服务器·网络·c++·网络协议·tcp/ip
Q3_SkyAsh13 分钟前
【电子取证】——第三届“平航杯”电子数据取证竞赛服务器取证部分
服务器·电子取证
大白菜和MySQL17 分钟前
apache服务器部署简记
运维·服务器·apache
极创信息26 分钟前
信创系统认证服务怎么做?从适配到验收全流程指南
java·大数据·运维·tomcat·健康医疗
格鸰爱童话33 分钟前
向AI学习项目技能(六)
java·人工智能·spring boot·python·学习
渣渣馬37 分钟前
rk3588s的firfly的linux的sdk版本
linux·运维·服务器
白宇横流学长1 小时前
停车场管理系统的设计与实现
java
Flittly1 小时前
【SpringAIAlibaba新手村系列】(18)Agent 智能体与今日菜单应用
java·spring boot·agent
木井巳1 小时前
【递归算法】目标和
java·算法·leetcode·决策树·深度优先