【问题标题】:Remove duplicated code from same method in different objects从不同对象的相同方法中删除重复代码
【发布时间】:2019-11-24 08:31:02
【问题描述】:

我有 2 个不同的对象,参数和变量,它们是上下文的字段。
我还有第三个对象:ParameterBase,它不是 Context 的一部分。
所有 3 个类都是自动生成的,我无法修改它们。
所有 3 个类都有 2 个字段:字符串类型的名称和值。
所有 3 个类都有 getter 和 setter。

我实现了以下方法:

public static List<ParametersBase> removeDuplicate(List<ParametersBase> parameterList) {
    return new ArrayList<>(parameterList.stream().collect(
            Collectors.toMap(
                    ParametersBase::getParamName,
                    Function.identity(),
                    Utils::mergeDuplicate
            )
    ).values());
}

private static ParametersBase mergeDuplicate(ParametersBase a, ParametersBase b) {
    if (a.getParamValue().equals(b.getParamValue())) {
        return a;
    } else {
        throw new IllegalArgumentException("Error message");
    }
}

我想对其他 2 个类使用此方法,所以我这样做了:

private static void removeDuplicatesParams(Context context) {
    final List<ParametersBase> parameterList = emptyIfNull(
        context.getParameters()).stream()
        .map(parameter -> new ParametersBase()
            .paramName(parameter.getParamName())
            .paramValue(parameter.getParamValue()))
        .collect(Collectors.toList());
    List<ParametersBase> distinctParameterList = removeDuplicate(parameterList);
    List<Parameter> distinctParametersList = distinctParameterList
        .stream().map(temp -> new Parameter().paramName(temp.getParamName())
            .paramValue(temp.getParamValue())).collect(Collectors.toList());
    context.setParameters(distinctParametersList);
}

private static void removeDuplicatesVariables(Context context) {
    final List<ParametersBase> parameterList = emptyIfNull(
        context.getVariables()).stream()
        .map(parameter -> new ParametersBase()
            .paramName(parameter.getParamName())
            .paramValue(parameter.getParamValue()))
        .collect(Collectors.toList());
    List<ParametersBase> distinctParameterList = removeDuplicate(parameterList);
    List<Variable> distinctParametersList = distinctParameterList
        .stream().map(temp -> new Variable().paramName(temp.getParamName())
            .paramValue(temp.getParamValue())).collect(Collectors.toList());
    context.setVariables(distinctParametersList);
}

如您所见,我创建的两个方法几乎相同,但由于我有 2 个自动生成的类,因此我必须复制代码。有没有办法让代码更漂亮?我正在使用 Java 8。

【问题讨论】:

  • 据我了解,您可以使用泛型解决此问题。也许这个可以帮助你:stackoverflow.com/questions/58890600/…
  • @Hubi 这里的情况有点不同,因为这个问题涉及到复杂的对象,所以需要映射。
  • 可以加removeDuplicate方法源码吗?我觉得可以泛化。
  • public static List removeDuplicate(List parameterList) { return new ArrayList(parameterList.stream().collect( Collectors.toMap(ParametersBase::getParamName, Function.identity( ), Utils::mergeDuplicate)) .values()); } 私有静态 ParametersBase mergeDuplicate(ParametersBase a, ParametersBase b) { if (a.getParamValue().equals(b.getParamValue())) { return a; } else { 抛出新异常(); } } @Bananon
  • 这三个类之间有继承关系吗?

标签: java oop object collections java-stream


【解决方案1】:

你可以生成removeDuplicate方法:

private static <T> List<T> removeDuplicate(
        Collection<? extends T> parameterList,
        Function<? super T, String> name,
        Function<? super T, String> value
) {
    return new ArrayList<>(parameterList.stream().collect(
            Collectors.<T, String, T>toMap(
                    name,
                    Function.identity(),
                    (a, b) -> mergeDuplicate(a, b, value)
            )).values()
    );
}

private static <T> T mergeDuplicate(T a, T b, Function<? super T, String> value) {
    if (value.apply(a).equals(value.apply(b))) return a;
    else throw new IllegalArgumentException("Error message");
}

并像这样使用它:

private static void removeDuplicatesParams(Context context) {
    context.setParameters(removeDuplicate(
            context.getParameters(),
            Parameter::getParamName,
            Parameter::getParamValue
    ));
}

或者你可以申请adapter design pattern:

private interface ParameterAdapter<T> {
    T original();
    String name();
    String value();
}

private static <T> List<T> removeDuplicate(
        Collection<? extends T> parameterList,
        Function<? super T, ? extends ParameterAdapter<T>> adapter
) {
    return parameterList.stream()
            .<ParameterAdapter<T>>map(adapter)
            .collect(Collectors.toMap(
                    ParameterAdapter::name,
                    Function.identity(),
                    Utils::mergeDuplicate
            )).values().stream()
            .map(ParameterAdapter::original)
            .collect(Collectors.toList());
}

private static <T> ParameterAdapter<T> mergeDuplicate(
        ParameterAdapter<T> a,
        ParameterAdapter<T> b
) {
    if (a.value().equals(b.value())) return a;
    else throw new IllegalArgumentException("Error message");
}

并像这样使用它:

private static void removeDuplicatesParams(Context context) {
    context.setParameters(removeDuplicate(
            context.getParameters(),
            Utils::adaptParameter
    ));
}

private static ParameterAdapter<Parameter> adaptParameter(Parameter parameter) {
    return new ParameterAdapter<Parameter>() {
        @Override
        public Parameter original() { return parameter; }

        @Override
        public String name() { return parameter.getParamName(); }

        @Override
        public String value() { return parameter.getParamValue(); }
    };
}

【讨论】:

  • 我使用了您建议的适配器设计模式。谢谢。
  • 您一定读懂了 OP 的想法,因为问题中没有任何信息表明整个操作是关于删除重复名称的。它也没有告诉我们您使用的合并逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多