【问题标题】:Java 8 Functional Programming - Need to write a generic function on classJava 8 函数式编程 - 需要在类上编写一个通用函数
【发布时间】:2023-04-09 19:39:01
【问题描述】:

我想创建一个接受类似这样的方法

set(nodeStatus, status, NodeStatus::setStatus, Status::valueOf);
set(nodeStatus, errorCode, NodeStatus::setErrorCode, ErrorCode::valueOf);

Status 和 ErrorCode 是 java 中的枚举。

签名和伪代码

set(NodeStatus nodeStatus, byte[] status, ?nodeStatusOperator , ?ValueTransformer) {
   1. convert byte[] status to appropriate value as per ValueTransformer
   2. nodeStatusOperator sets this transformed value according to the lambda passed.
}

我想知道在java中应该使用什么方法签名来完成这个以及为什么。我尝试了各种消费者、BiConsumers 等,但无法做到这一点。有人可以帮忙吗?

【问题讨论】:

    标签: java lambda functional-programming producer-consumer


    【解决方案1】:

    据我所知,您需要的是:

    public <T> void set (NodeStatus nodeStatus, 
                         byte [] value, 
                         BiConsumer<NodeStatus,T> setter, 
                         Function<byte[],T> transformer) {
        T transformedValue = transformer.apply(value);
        setter.accept(nodeStatus, transformedValue);
    }
    

    (如果value 可以是byte[] 以外的值,则可以将其替换为其他类型参数。)

    Ps:setterBiConsumer,因为你在实例方法上使用了静态方法引用(例如NodeStatus::setErrorCode),所以BiConsumer的第一个参数必须是NodeStatus实例@987654330 @ 将被调用。

    P.p.s:正如glglgl 所指出的,您可以将代码简化为:

    public <T> void set (byte [] value, 
                         Consumer<T> setter, 
                         Function<byte[],T> transformer) {
        T transformedValue = transformer.apply(value);
        setter.accept(transformedValue);
    }
    

    然后这样称呼它:

    set(status, nodeStatus::setStatus, Status::valueOf);
    

    ...其中nodeStatus 是您要操作的NodeStatus 的实例。

    【讨论】:

    • OP 没有说明他是否允许这样做,但如果是这样,我会将其细化为public &lt;T&gt; void set (byte [] value, Consumer&lt;T&gt; setter, Function&lt;byte[],T&gt; transformer) { T transformedValue = transformer.apply(value); setter.accept(transformedValue); } ,包括状态对象到 setter 方法引用中。然后电话就像set(status, nodeStatus::setStatus, Status::valueOf); set(errorCode, nodeStatus::setErrorCode, ErrorCode::valueOf);
    • @glglgl 你说得对,这样看起来会干净很多。我只是使用提供的签名 OP,但我会编辑我的答案。
    • 感谢大家 - 如此快速的响应和对泛型的出色使用
    【解决方案2】:

    有点不清楚您要达到的目标。当您可以只传递适用于特定 NodeStatus 实例的函数时,为什么要传递 NodeStatus 和函数,例如:

    static <T> void set(byte[] status, Consumer<T> nodeStatusOperator, Function<String, T> transformer) {
        nodeStatusOperator.accept(transformer.apply(new String(status)));
    }
    
    public static void main(String[] args) {
        NodeStatus nodeStatus = new NodeStatus();
        byte[] status = new byte[0];
        set(status, nodeStatus::setStatus, Status::valueOf);
        set(status, nodeStatus::setErrorCode, ErrorCode::valueOf);
    }
    

    与更直接的方法相比,这种通用性能为您带来什么?

    nodeStatus.setStatus(Status.valueOf(new String(status)));
    nodeStatus.setErrorCode(ErrorCode.valueOf(new String(status)));
    

    【讨论】:

    • new String(status) 对于所有枚举都是通用的。同样,在我的班级中,还有多个其他设置器,例如 Date 转换不同的地方。还有字符串设置器。此外,我可以对相同类型的多个设置器的转换值应用一些常规检查,从而减少代码行。示例:nodeStatus.setUpdateTs(new Date(BinaryUtils.bytesToLong(updateTs))
    猜你喜欢
    • 2020-10-02
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    • 2018-12-07
    • 2020-12-31
    • 1970-01-01
    • 2015-07-03
    • 1970-01-01
    相关资源
    最近更新 更多