对多种功能执行相同的操作

时间:2019-04-05 13:54:26

标签: java dictionary java-8 optional

我有一个包含多个get函数的类,例如getF1getF10。对于每个这些吸气剂,我都希望将字母"x"替换为"a"(随机示例)。该getter可以返回一个空值。

到目前为止,这是我所做的并且有效,是否有办法使外观比这更好?

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"));
}

也许与流一起工作可以完成工作?

谢谢!

2 个答案:

答案 0 :(得分:3)

您可以将Optional::map中使用的映射器和Optional::ifPresent中使用的使用者存储在Map中。

我还建议您创建一种方法,以避免替换String的代码重复,该方法应易于调用。这很有用,因为所有替换项都相同

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的每个String应用不同的功能,则还需要使用不同的结构:

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);
});

答案 1 :(得分:3)

您可以将SupplierConsumer配对的getter和setter进行迭代:

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"))));
}

还请注意,由null处理的Optional参数已由保护子句代替:必须在解析bar::...之前执行此操作以防止NPE。它还使预期的null处理更加清晰。