在迭代地对列表应用操作时减少 Java 代码重复,直到稳定

Reducing Java code-duplication when iteratively applying an operation on a list until stable

提问人:Caleb 提问时间:4/12/2023 最后编辑:Caleb 更新时间:4/12/2023 访问量:43

问:

我正在尝试减少 java 代码中的代码重复。我不是 Java 专家,所以我可能会错过一些基本的东西。目标是通过多个运算符对列表进行操作。foo1, foo2, ..., fooN

每个操作都会迭代,直到列表稳定(不再因操作而更改)。每个操作都由前向传递和向后传递组成。传递是相同的,只是列表是颠倒的。每个传递也会迭代,直到列表稳定下来。运算符必须按顺序应用,这会导致令人沮丧的代码重复。

下面是一些伪 java,展示了它目前是如何完成的。注意:此处的操作尝试修改列表;当(且仅当)发生修改时,它们返回 true。fooarg1arg1

reduceByFoo1(arg1,arg2,arg3){
        doUpdate = true;
        while(doUpdate) {
            doUpdate = false;

            doPass = true;
            while(doPass) {
                doPass = foo1(arg1,arg2,arg3);
                doUpdate |= doPass;
            }
            Collections.reverse(arg1);

            doPass = true;
            while(doPass) {
                doPass = foo1(arg1,arg2,arg3);
                doUpdate |= doPass;
            }
            Collections.reverse(arg1);
        }
    }

reduceByFoo2(arg1,arg2,arg3){
...same code as above, but with foo2..
}

reduceByFoo2(arg1,arg2,arg3){
...same code as above, but with foo3..
}

...and so on...

减少重复或改进设计模式的好方法是什么?

编辑: 使用公认的答案,这大致是我最终得到的代码。现在好多了:

interface Foo {boolean bar(arg1, arg2, arg3);}

fooUntilStable(foo, arg1, arg2, arg3) = {
    iterate = true;
    updated = false;
    while(iterate) {
        iterate = foo.bar(arg1, arg2, arg3);
        updated |= iterate;
    }
    return updated;
}

biFooUntilStable(foo, arg1, arg2, arg3){
    Foo biFoo = (a1, a2, a3) -> {
             updated = fooUntilStable(foo, a1, a2, a3);
             Collections.reverse(a1);
             updated |= fooUntilStable(foo, a1, a2, a3);
             Collections.reverse(a1);
             return updated;
    }
    fooUntilStable(biFoo,arg1,arg2,arg3);
}

Foo foo1 = (arg1,arg2,arg3) -> {...}
Foo foo2 = (arg1,arg2,arg3) -> {...}
...
Foo fooN = (arg1,arg2,arg3) -> {...}

biFooUntilStable(foo1,arg1,arg2,arg3);
biFooUntilStable(foo2,arg1,arg2,arg3);
...
biFooUntilStable(fooN,arg1,arg2,arg3);

Java 代码复制 冗余 反模式

评论

1赞 Dave Newton 4/12/2023
没有太多的背景信息,很难提供帮助。至少看起来缺少一个列表抽象,可以接受一个接口进行操作。foo

答:

1赞 Chase C 4/12/2023 #1

我处理执行相同操作但略有不同的函数的方式是这样的:

reduceByFoo1(arg1,arg2,arg3){
   // do common operation
   foo1(arg1, arg2, arg3);
   // do stuff
}


reduceByFoo2(arg1,arg2,arg3){
   // do common operation
   foo2(arg1, arg2, arg3);
   // do stuff
}

在其他编程语言中,我们可以将函数作为参数传递,但 Java 略有不同。查看这篇文章,了解如何将方法作为参数传递。

但我要做的是:

public void reduce(arg1, arg2, arg3, someFunc) {
   // do common operation
   someFunc(arg1, arg2, arg3);
   // do common operation
}

根据上述 SO 帖子中的信息。

,您可以使用指定的函数调用reduce,例如:

reduceByFoo1(arg1,arg2,arg3){
   // do common operation
   reduce(arg1, arg2, arg3, foo1);
   // do stuff
}


reduceByFoo2(arg1,arg2,arg3){
   // do common operation
   reduce(arg1, arg2, arg3, foo2);
   // do stuff
}

编辑添加:这篇其他帖子提供了可能更适合您的请求的其他想法。