Java 如何清理我的代码

Java 如何清理我的代码,java,refactoring,Java,Refactoring,作为一个新手,我真的在努力学习如何让代码尽可能简单,同时完成它应该做的工作 它说,我所做的问题来自 斐波那契序列中的每个新项都是通过添加 前两届。从1开始 第二,前10个条款为: 求序列中所有偶数值项的和 不超过四百万 下面是我的代码。我想知道简化这个的最好方法是什么,首先删除所有的.get(list.length()-1)。。。。。如果可能的话,这将是一个好的开始,但我真的不知道如何开始 谢谢 public long fibb() { ArrayList<Integer>

作为一个新手,我真的在努力学习如何让代码尽可能简单,同时完成它应该做的工作

它说,我所做的问题来自

斐波那契序列中的每个新项都是通过添加 前两届。从1开始 第二,前10个条款为:

求序列中所有偶数值项的和 不超过四百万

下面是我的代码。我想知道简化这个的最好方法是什么,首先删除所有的.get(list.length()-1)。。。。。如果可能的话,这将是一个好的开始,但我真的不知道如何开始

谢谢

public long fibb()
{
    ArrayList<Integer> list = new ArrayList<Integer>();


    list.add(1);
    list.add(2);

    while((list.get(list.size() - 1) +  (list.get(list.size() - 2)) < 4000000)){  
        list.add((list.get(list.size()-1)) + (list.get(list.size() - 2)));
    }     

    long value = 0;
    for(int i = 0; i < list.size(); i++){
        if(list.get(i) % 2 == 0){
            value += list.get(i);
        }    
    }
    return value;
}
public long fibb()
{
ArrayList=新建ArrayList();
增加第(1)款;
增加(2);
而((list.get(list.size()-1)+(list.get(list.size()-2))<4000000)){
add((list.get(list.size()-1))+(list.get(list.size()-2));
}     
长值=0;
对于(int i=0;i
您不需要列表,只需要最后两项。这里有一些伪代码,我把它翻译成你的语言留给你

f0=1 #pre-last number
f1=1 #last number
while(...) {
    t = f0 + f1
    if (t%2 == 0) # replaces your second loop 
         sum += t 
    f0 = f1
    f1 = t
}
接下来,您可以观察到数字总是按顺序排列的:

odd, odd, even, odd, odd, even [...]
如果您需要进一步优化,我的建议是(我不会提供答案,因为最好自己得出结论)


试着想想为什么需要存储序列的值?你的程序将在一个大数组中存储4000000个整数,真的需要吗?您可以只使用2个项目,然后快速(使用斐波那契计算)将偶数添加到一个总变量中

您可以完全删除该列表。只需将最后两个斐波那契数保留在两个变量中,然后在循环中计算下一个(与第一个循环类似)


然后在同一个循环中保持与条件匹配的所有数字的运行总数(即,偶数小于百万)。

首先,在尝试重写任何代码之前,进行单元测试是很有用的。即使是最明显的变化也能打破一些意想不到的事情

其次,非常小心是很重要的。您经常会在代码中看到,对相同函数的X调用可以被一个调用、变量赋值和该变量的使用所取代

然而,你必须小心这样做。例如,在当前代码中,无法真正替换list.size(),因为在同一次迭代中,调用之间的大小一直在变化


最让您的代码难以理解的是,您在更新列表时引用了列表索引。您需要将索引保存到变量中,分成多行,也许还需要添加一些注释以使其更具可读性。

如果不保护列表中的所有值,您将做大量简化。你可以检查他们是否“在逃”

例如:

int old, current;
old = 1;
current = 1;

long value = 0;

while(current < 4000000) {
 if(current % 2  == 0) value += current;

 int tmp = old + current;
 old = current;
 current = tmp;
}

return value;
int旧,当前;
old=1;
电流=1;
长值=0;
而(电流<4000000){
如果(当前%2==0)值+=当前值;
int tmp=旧+电流;
旧=当前;
电流=tmp;
}
返回值;

首先,斐波那契序列的一个成员由前面的两个值生成。为什么不在缓冲区中保留两个数字,然后测试该数字是否为偶数。如果是偶数,把它加到你的总数中,当你达到400万时停止

代码:

public int fibEvenSum(int a,int b){
整数和=0;
INTC=a+b;

虽然(c其他响应者都给出了很好的答案。我想向你展示重构是如何运作的,不仅仅是为了解决这个特定的问题,了解斐波那契数,而是作为一个迭代过程,仔细地将代码缩减到最低限度。重构让我们从复杂的代码开始,并稳步地缩减代码一步一个脚印。让我向你展示你在朝着最终解决方案前进的过程中可以采取的所有中间步骤

注意:我已将初始起始值改为1和1,而不是1和2。严格来说,斐波那契序列从两个1开始,如1,1,2,3,5

步骤1-颠倒列表 首先,为了摆脱重复的
list.size()-x
表达式,可以按相反顺序添加数字。然后查找最近的两个数字更简单

public long fibb()
{
    ArrayList<Integer> list = new ArrayList<Integer>();

    list.add(1);
    list.add(1);

    while (list.get(0) + list.get(1) < 4000000) {
        // Use list.add(0, ...) to add entries to the *front*.
        list.add(0, list.get(0) + list.get(1));
    }     

    long value = 0;

    for (int i = 0; i < list.size(); i++) {
        if (list.get(i) % 2 == 0) {
            value += list.get(i);
        }    
    }

    return value;
}
步骤3-组合循环 下一个优化是将两个循环组合起来,而不是先生成所有的数字,然后再检查偶数,而是在生成偶数时检查偶数

public long fibb()
{
    List<Integer> list = new LinkedList<Integer>();
    long value = 0;

    list.add(1);
    list.add(1);

    while (list.get(0) + list.get(1) < 4000000) {
        int next = list.get(0) + list.get(1);

        list.add(0, next);

        if (next % 2 == 0) {
            value += next;
        }    
    }     

    return value;
}

我会删除这个列表。你在这里做了两次迭代,而你真正需要做的就是在序列上迭代,并在运行时保留一个tally变量

  • 因此,使用某种for/while循环迭代斐波那契序列
  • 如果是偶数,则将其添加到tally变量
要在序列上进行简单的迭代,只需记录两个最新的值(f(n)和f(n-1))和(取决于您的语言)一个临时变量,以便在更新这些值时使用。通常情况下:

temp = current;
current = current + previous; // temp holds old value of current so the next line works.
previous = temp;
simples方法是一种基本的for循环。或者,如果您想成为接口的所有OO,您可以滚动实现接口的自己的类。然后,您的代码可以简单到:

Fib fib = new Fib();
for(long n : fib) {
    if(n % 2 == 0) t += n;
}

这提醒了我,总有一天我必须再次回到Euler中。

在Python中,一切看起来都更漂亮

def fibb():
    ret = 2 # to take into account the first 2
    fib = [1, 2]

    while True:
        latest = fib[-1] + fib[-2]
        if latest >= 4000000: return ret

        fib.append(latest)
        if latest % 2 == 0: ret += latest
注意:这更像是一个编程练习,我意识到转移到Python可能并不实际

编辑,这是一种更高效的无列表方法:

def fibb():
    ret = 0
    f0, f1 = (1, 1)

    while True:
        f0, f1 = (f1, f0 + f1)
        if f1 >= 4000000: return ret
        if f1 % 2 == 0: ret += f1

类似于@John Kugelman的解决方案,但效率更高。这将只循环1/3的时间,每个循环更短,分支更少,甚至不需要测试。这充分利用了
temp = current;
current = current + previous; // temp holds old value of current so the next line works.
previous = temp;
Fib fib = new Fib();
for(long n : fib) {
    if(n % 2 == 0) t += n;
}
def fibb():
    ret = 2 # to take into account the first 2
    fib = [1, 2]

    while True:
        latest = fib[-1] + fib[-2]
        if latest >= 4000000: return ret

        fib.append(latest)
        if latest % 2 == 0: ret += latest
def fibb():
    ret = 0
    f0, f1 = (1, 1)

    while True:
        f0, f1 = (f1, f0 + f1)
        if f1 >= 4000000: return ret
        if f1 % 2 == 0: ret += f1
public static long fibb() {
    int a = 1, b = 1;
    long total = 0;
    while (true) {
        int c = a + b;
        if (c >= 4000000) return total;
        total += c;
        a = b + c;
        b = c + a;
    }
}