对多个函数执行相同的操作
Performing same operation on multiple functions
我有一个 class 具有多个 get
功能,例如 getF1
到 getF10
。对于这些 getter 中的每一个,我想将字母 "x"
替换为 "a"
(随机示例)。 getter 可以 return 空值。
到目前为止,这是我所做的并且有效,有没有比这更好看的方法?
public void foo(final MyObject bar) {
Optional.of(bar).map(MyObject::getF1).ifPresent(s -> bar.setF1(s.replaceAll("x", "a"));
Optional.of(bar).map(MyObject::getF2).ifPresent(s -> bar.setF2(s.replaceAll("x", "a")));
...
Optional.of(bar).map(MyObject::getF10).ifPresent(s -> bar.setF10(s.replaceAll("x", "a")));
}
我在想这样的事情,使用列表,显然,这段代码是错误的,但你明白了:
public void foo(final MyObject bar) {
List<Function> func = new ArrayList<Function>();
func.addAll(Arrays.asList(MyObject::getF1, MyObject::getF2, ..., MyObject::getF10));
Optional.of(bar).map(func).ifPresent(s -> func(s.replaceAll("x", "a"));
}
也许使用流可以完成工作?
谢谢!
您可以将 Optional::map
中使用的映射器和 Optional::ifPresent
中使用的消费者存储在 Map
中。
我还建议你创建一个方法来避免字符串替换的代码重复,应该很容易调用。这很有用,因为所有替换都是相同的
private String replaced(String string) {
return string.replaceAll("x", "a");
}
然后简单地遍历条目并应用每个键值对(顺序无关紧要):
Map<Function<? super MyObject, ? extends String>, Consumer<? super String>> map = new HashMap<>();
map.put(MyObject::getF1, bar::setF1);
map.put(MyObject::getF2, bar::setF2);
map.put(MyObject::getF10, bar::setF10);
// ...
map.forEach((function, consumer) -> {
Optional.of(bar).map(function).map(this::replaced).ifPresent(consumer);
});
如果您想扩展此机制并对传递给 setter 的每个字符串应用不同的函数,那么您还需要使用不同的结构:
public final class Mapping {
private final Function<MyObject, String> getterFunction;
private final Function<String, String> transformationFunction;
private final Consumer<String> setterFunction;
public Mapping(final Function<MyObject, String> getterFunction, final Function<String, String> transformationFunction,
final Consumer<String> setterFunction) {
this.getterFunction = getterFunction;
this.transformationFunction = transformationFunction;
this.setterFunction = setterFunction;
}
// getters
}
用法类似(转换函数是示例,可能会有所不同):
List<Mapping> list = new ArrayList<>();
list.add(new Mapping(MyObject::getF1, s -> s.replaceAll("x", "a"), bar::setF1));
list.add(new Mapping(MyObject::getF2, s -> s.replaceAll("x", "a"), bar::setF2));
list.add(new Mapping(MyObject::getF10, s -> s.replaceAll("x", "a"), bar::setF10));
list.forEach(mapping -> {
Optional.of(bar)
.map(mapping.getGtterFunction)
.map(mapping.getTransformationFunction)
.ifPresent(mapping.getSetterFunction);
});
您可以迭代成对的 getter 和 setter Supplier
s and Consumer
s:
public void foo(final MyObject bar) {
if (bar == null)
return;
Map<Supplier<String>, Consumer<String>> funcs = new HashMap<>();
funcs.put(bar::getF1, bar::setF1);
funcs.put(bar::getF2, bar::setF2);
funcs.forEach(
(getter, setter) -> Optional.of(getter.get()).ifPresent(s -> setter.accept(s.replaceAll("x", "a"))));
}
另请注意,Optional
处理的 null
参数已被保护子句取代:这必须在解析 bar::...
之前出现,以防止 NPE。它还使预期的 null
处理更加清晰。
我有一个 class 具有多个 get
功能,例如 getF1
到 getF10
。对于这些 getter 中的每一个,我想将字母 "x"
替换为 "a"
(随机示例)。 getter 可以 return 空值。
到目前为止,这是我所做的并且有效,有没有比这更好看的方法?
public void foo(final MyObject bar) {
Optional.of(bar).map(MyObject::getF1).ifPresent(s -> bar.setF1(s.replaceAll("x", "a"));
Optional.of(bar).map(MyObject::getF2).ifPresent(s -> bar.setF2(s.replaceAll("x", "a")));
...
Optional.of(bar).map(MyObject::getF10).ifPresent(s -> bar.setF10(s.replaceAll("x", "a")));
}
我在想这样的事情,使用列表,显然,这段代码是错误的,但你明白了:
public void foo(final MyObject bar) {
List<Function> func = new ArrayList<Function>();
func.addAll(Arrays.asList(MyObject::getF1, MyObject::getF2, ..., MyObject::getF10));
Optional.of(bar).map(func).ifPresent(s -> func(s.replaceAll("x", "a"));
}
也许使用流可以完成工作?
谢谢!
您可以将 Optional::map
中使用的映射器和 Optional::ifPresent
中使用的消费者存储在 Map
中。
我还建议你创建一个方法来避免字符串替换的代码重复,应该很容易调用。这很有用,因为所有替换都是相同的
private String replaced(String string) {
return string.replaceAll("x", "a");
}
然后简单地遍历条目并应用每个键值对(顺序无关紧要):
Map<Function<? super MyObject, ? extends String>, Consumer<? super String>> map = new HashMap<>();
map.put(MyObject::getF1, bar::setF1);
map.put(MyObject::getF2, bar::setF2);
map.put(MyObject::getF10, bar::setF10);
// ...
map.forEach((function, consumer) -> {
Optional.of(bar).map(function).map(this::replaced).ifPresent(consumer);
});
如果您想扩展此机制并对传递给 setter 的每个字符串应用不同的函数,那么您还需要使用不同的结构:
public final class Mapping {
private final Function<MyObject, String> getterFunction;
private final Function<String, String> transformationFunction;
private final Consumer<String> setterFunction;
public Mapping(final Function<MyObject, String> getterFunction, final Function<String, String> transformationFunction,
final Consumer<String> setterFunction) {
this.getterFunction = getterFunction;
this.transformationFunction = transformationFunction;
this.setterFunction = setterFunction;
}
// getters
}
用法类似(转换函数是示例,可能会有所不同):
List<Mapping> list = new ArrayList<>();
list.add(new Mapping(MyObject::getF1, s -> s.replaceAll("x", "a"), bar::setF1));
list.add(new Mapping(MyObject::getF2, s -> s.replaceAll("x", "a"), bar::setF2));
list.add(new Mapping(MyObject::getF10, s -> s.replaceAll("x", "a"), bar::setF10));
list.forEach(mapping -> {
Optional.of(bar)
.map(mapping.getGtterFunction)
.map(mapping.getTransformationFunction)
.ifPresent(mapping.getSetterFunction);
});
您可以迭代成对的 getter 和 setter Supplier
s and Consumer
s:
public void foo(final MyObject bar) {
if (bar == null)
return;
Map<Supplier<String>, Consumer<String>> funcs = new HashMap<>();
funcs.put(bar::getF1, bar::setF1);
funcs.put(bar::getF2, bar::setF2);
funcs.forEach(
(getter, setter) -> Optional.of(getter.get()).ifPresent(s -> setter.accept(s.replaceAll("x", "a"))));
}
另请注意,Optional
处理的 null
参数已被保护子句取代:这必须在解析 bar::...
之前出现,以防止 NPE。它还使预期的 null
处理更加清晰。