Java 8 种组合,柯里化 shorthand
Java 8 Composition, Currying shorthand
我有一个 BusinessObject
流,我需要为每个对象设置一个值,我想使用 Stream.map
但 map
需要一个 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>
,那么 SomeDiscriminator
和 String
值都不是流元素。
所以这是一个 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 一个动态函数。
我有一个 BusinessObject
流,我需要为每个对象设置一个值,我想使用 Stream.map
但 map
需要一个 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>
,那么 SomeDiscriminator
和 String
值都不是流元素。
所以这是一个 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 一个动态函数。