Java 8 种组合,柯里化 shorthand

Java 8 Composition, Currying shorthand

我有一个 BusinessObject 流,我需要为每个对象设置一个值,我想使用 Stream.mapmap 需要一个 Function<T,R> 并且我有目标对象、鉴别器值和新值。 setNewValueInBusinessObjectExample 显示了我想做的事情,setNewValueInBusinessObjectWithFun 是我需要帮助的事情。

同意!我可以只在地图上使用 setNewValueInBusinessObjectExample,但我想看看功能样式如何。谢谢

class BusinessObject {
    String firstField;
    String secondField;
}

class SomeDiscriminator {
    String value;
}

BusinessObject setNewValueInBusinessObjectExample(BusinessObject businessObject, 
     SomeDiscriminator discriminator, String newValue) {

    if(discriminator.value.equals("firstField")) {
        businessObject.firstField = newValue;
    } else {//secondField
        businessObject.secondField = newValue;
    }

    return businessObject;
}

Function<BusinessObject, Function<SomeDiscriminator, Function<String, BusinessObject>>> 
       setNewValueInBusinessObjectWithFun = {
    /* todo: using nested Function<T,R> */
}

不完全确定我得到了你可能需要的东西,但像这样的东西?

static Function<BusinessObject, Function<SomeDiscriminator, Function<String, BusinessObject>>>
    setNewValueInBusinessObjectWithFun =
    x -> y -> z -> {
        if ("firstfield".equals(y.value)) {
            x.firstField = z;
        } else {
            x.secondField = z;
        }
        return x;
    };

用法为:

    BusinessObject bo = new BusinessObject();
    bo.firstField = "test";

    SomeDiscriminator sd = new SomeDiscriminator();
    sd.value = "firstField";
    bo = setNewValueInBusinessObjectWithFun.apply(bo).apply(sd).apply("value");

    System.out.println(bo.firstField);

如果您对功能接口的构造和使用有疑问,我建议您将整个事情扩展到结构变得明显的匿名 classes。

我还注意到整个流程使用了三个参数,与您的 setNewValueInBusinessObjectExample 一样。因此将方法体移动到最里面的匿名class.

Function<BusinessObject, Function<SomeDiscriminator, Function<String, BusinessObject>>> setNewValueInBusinessObjectWithFun =
    new Function<BusinessObject, Function<SomeDiscriminator, Function<String, BusinessObject>>>() {
        @Override
        public Function<SomeDiscriminator, Function<String, BusinessObject>> apply(final BusinessObject businessObject) {
            return new Function<SomeDiscriminator, Function<String, BusinessObject>>() {
                @Override
                public Function<String, BusinessObject> apply(final SomeDiscriminator someDiscriminator) {
                    return new Function<String, BusinessObject>() {
                        @Override
                        public BusinessObject apply(final String newValue) {
                            if (someDiscriminator.value.equals("firstField")) {
                                businessObject.firstField = newValue;
                            } else {//secondField
                                businessObject.secondField = newValue;
                            }
                            return businessObject;
                        }
                    };
                }
            };
        }
    };

现在,将所有内容打包到 lambda 表达式中,看看会发生什么:

Function<BusinessObject, Function<SomeDiscriminator, Function<String, BusinessObject>>> setNewValueInBusinessObjectWithFun = 
    businessObject -> someDiscriminator -> newValue -> {
        if (someDiscriminator.value.equals("firstField")) {
            businessObject.firstField = newValue;
        } else {//secondField
            businessObject.secondField = newValue;
        }
        return businessObject;
    };

为了清楚起见,请正确命名 lambda 表达式中的变量,否则您将无法很好地使用它们。用法相当简单(为了简洁起见,我将 setter 移到了构造函数中:

BusinessObject businessObject = new BusinessObject("oldValue");
setNewValueInBusinessObjectWithFun
    .apply(businessObject)                                  // apply to an object
    .apply(new SomeDiscriminator("firstField"))             // finds its field
    .apply("newValue");                                     // sets a new value

但是,我建议您定义一个自定义 @FunctionalInterface,定义更直接...

@FunctionalInterface
interface MyFunction<T, R, U> {
    T apply(T t, R r, U u);
}

...和用法...

MyFunction<BusinessObject, SomeDiscriminator, String> myFunction = 
    (businessObject, someDiscriminator, newValue) -> {
        if (someDiscriminator.value.equals("firstField")) {
            businessObject.firstField = newValue;
        } else {
            businessObject.secondField = newValue;
        }
        return businessObject;
    };

BusinessObject businessObject = new BusinessObject("oldValue");
myFunction.apply(businessObject, new SomeDiscriminator("firstField"), "newValue");

这不需要很复杂。如果您有 Stream<BusinessObject>,那么 SomeDiscriminatorString 值都不是流元素。

所以这是一个 Function<BusinessObject, BusinessObject> 你需要传递给 map:

Stream<BusinessObject> businessObjectStream = null;
SomeDiscriminator discriminator = null; String newValue = "";

Function<BusinessObject, BusinessObject> mapper = businessObject -> {
    if (discriminator.value.equals("firstField")) {
        businessObject.firstField = newValue;
    } else {//secondField
        businessObject.secondField = newValue;
    }

    return businessObject;
};

调用方式:

businessObjectStream.map(mapper);

即使 discriminator.value.equals("firstField") 逻辑依赖于流对象中的动态值,您可能在某处需要一个 Predicate<...>,但实际上甚至不需要 returns 一个动态函数。