如何重构这个java代码

时间:2015-02-05 00:59:55

标签: java refactoring

我有下面这个名为solution的java方法,有两个大的for循环,正如你所看到的,两个for循环是非常samilar,所以我认为有可能通过像这样的方法来重构代码public int getElementSize(ArrayList<Integer> factor1, ArrayList<Integer> factor2)执行for循环的工作,所以我可以用不同的参数调用该方法两次,而不是重复两个for循环。但是因为这两个for循环有不同的循环次序,一个是从头到尾,另一个是从尾到头,除此之外,循环的所有其他部分是相同的,任何想法如何重构这段代码?

class Solution {
    public int solution(int[] A) {
        ArrayList<Integer> factor1 = new ArrayList<Integer>();
        ArrayList<Integer> factor2 = new ArrayList<Integer>();

        int factor = 1;
        int N = A.length;
        while(factor * factor <= N){
            if(N % factor == 0){
                factor1.add(factor);
                factor2.add(N / factor);
            }
            factor++;
        }

        for(int i = 1; i < factor2.size(); i++){
            int blockSize = factor2.get(i);
            int elementSize = factor1.get(i);
            int peaks = 0;
            for(int j = 0; j < blockSize; j++){
                boolean hasPeak = false;
                for(int k = elementSize * j; k < elementSize * (j + 1); k++){
                    if(k > 0 && k < N - 1){
                        if(A[k] > A[k - 1] && A[k] > A[k + 1])
                            hasPeak = true;
                    }    
                } 
                if(!hasPeak)
                   break; 
                else
                   peaks++;
            }
            if(peaks == blockSize)
                return blockSize;
        }

        for(int i = factor1.size() - 1; i >= 0; i--){
            int blockSize = factor1.get(i);
            int elementSize = factor2.get(i);
            int peaks = 0;
            for(int j = 0; j < blockSize; j++){
                boolean hasPeak = false;
                for(int k = elementSize * j; k < elementSize * (j + 1); k++){
                    if(k > 0 && k < N - 1){
                        if(A[k] > A[k - 1] && A[k] > A[k + 1])
                            hasPeak = true;
                    }    
                } 
                if(!hasPeak)
                   break; 
                else
                   peaks++;
            }
            if(peaks == blockSize)
                return blockSize;    
        }

        return 0;
    }
}

2 个答案:

答案 0 :(得分:1)

这个怎么样?

有条件的算子,?和:类似于,(这些被称为三元运算符,在编译时解析为if else块)

if(condition) {
this();
} else { 
that();
}

在上面,你可以单行作为,(条件?this():that())

class Solution {
public int solution(int[] A) {
    ArrayList<Integer> factor1 = new ArrayList<Integer>();
    ArrayList<Integer> factor2 = new ArrayList<Integer>();

    int factor = 1;
    int N = A.length;
    while(factor * factor <= N){
        if(N % factor == 0){
            factor1.add(factor);
            factor2.add(N / factor);
        }
        factor++;
    }
    // let i = 0 to be factor2, i = 1 is factor 1
    for(int i = 0; i < 2; i++) { 
    for(int x = (i == 0 ? 1 : factor1.size() - 1); (i == 0 ? x < factor2.size() : x >= 0); (i == 0 ? x++ : x--)){
        int blockSize = (i == 0 ? factor2.get(x) : factor1.get(x));
        int elementSize = (i == 0 ? factor1.get(x) : factor2.get(x));
        int peaks = 0;
        for(int j = 0; j < blockSize; j++){
            boolean hasPeak = false;
            for(int k = elementSize * j; k < elementSize * (j + 1); k++){
                if(k > 0 && k < N - 1){
                    if(A[k] > A[k - 1] && A[k] > A[k + 1])
                        hasPeak = true;
                }    
            } 
            if(!hasPeak)
               break; 
            else
               peaks++;
        }
        if(peaks == blockSize)
            return blockSize;
            }
        }

    return 0;
    }
}

答案 1 :(得分:0)

你可以将for循环中的代码重构为新方法,然后将两个大的for循环移动到新方法,这样,两个循环的顺序仍然是独立的,基本上它看起来如下,正确性需要验证,这只是一个不重复的想法:

    class Solution {
    public int solution(int[] A) {
        ArrayList<Integer> factor1 = new ArrayList<Integer>();
        ArrayList<Integer> factor2 = new ArrayList<Integer>();       
        int factor = 1;
        int N = A.length;
        while(factor * factor <= N){
            if(N % factor == 0){
                factor1.add(factor);
                factor2.add(N / factor);
            }
            factor++;
        }

        for(int i = 1; i < factor2.size(); i++){
            int blockSize = factor2.get(i);
            int elementSize = factor1.get(i);
            int peaks = getElementSize(A, blockSize, elementSize); //call the method
            if(peaks == blockSize)
                return blockSize;
        }

        for(int i = factor1.size() - 1; i >= 0; i--){
            int blockSize = factor1.get(i);
            int elementSize = factor2.get(i);
            int peaks = getElementSize(A, blockSize, elementSize); //call the method
            if(peaks == blockSize)
                return blockSize;    
        }

        return 0;
    }

    //this method include the code which was repeated inside the loops 
    public int getElementSize(int[] A, int blockSize, int elementSize){
        int peaks = 0;
        int N = A.length;
        for(int j = 0; j < blockSize; j++){
            boolean hasPeak = false;
            for(int k = elementSize * j; k < elementSize * (j + 1); k++){
                if(k > 0 && k < N - 1){
                    if(A[k] > A[k - 1] && A[k] > A[k + 1])
                        hasPeak = true;
                }    
            } 
            if(!hasPeak)
                break; 
            else
                peaks++;
        }

        return peaks;
    }
}