java: 重构编码密码

java: refactor encode cipher

所以我实现了一个带有换位密码的编码方法,我提供了一个密钥和一条文本消息。

算术排序
D D E U
0 1 2 3
h l l e
o r o b

然后按列“阅读”:加密消息:“holrloeb”

import java.util.*;

public class test1 {

    public static String encode(String textraw, String key){
        int csize = 0, index = 0;
        int[] numbers = {0,3,1,2};
        int mod = textraw.length() % key.length();
        int div = textraw.length() / key.length();
        // calculate size of column
        if (mod == 0) {
            csize = div;
        } else {
            csize = div + 1;
        }
        int[] snumbers = numbers.clone();
        Arrays.sort(snumbers);

        // Sort columns
        StringBuilder str = new StringBuilder(textraw.length());

        for (int i = 0; i < numbers.length; i++) {
            for (int j = 0; j < numbers.length; j++) {
                if (snumbers[i] == numbers[j]){
                    index = snumbers[j];
                    break;
                }
            }

            // create string column by column
            for (int j = 0; j < csize; j++) {
                if (index < textraw.length()) {
                    str.append(textraw.charAt(index));
                    index += numbers.length;
                }
            }
        }
        return str.toString();
    }
    public static void main(String[] args){
        String s = "hellobro";
        String keyk = "DUDE";
        System.out.println("encrypted -> "+encode(s,keyk));
    }

}

我的问题是如何重构 encode 方法,至少摆脱第二个嵌套的 for 循环?

我试过省略索引,但还没有让它工作..
任何帮助将不胜感激!

一般备注

重构和代码风格在某种程度上是个人化的。所以我想并不是所有人都同意我的看法。 一些好的做法是确保您的代码简洁,但 class、方法和变量名称也应反映它们 and/or 的作用。您选择的名称应该有助于阅读代码。如果方法太长,请创建一个新方法以提高可读性。 在您当前的代码中,您可以用另一种方法替换 csize 的计算。您还可以选择更具可读性的变量,例如更改变量 str。 有关于正确 Java 代码的完整书籍。 Martin Fowler 写了一个比较流行的。所以,这些小言论根本没有涵盖重构主题。

你的方法的目标

你解释了你想做什么。但是,您的密钥(DUDE)的用途似乎不清楚。它实际上没有被使用。如果您使用其他键测试您的代码,它具有完全相同的顺序。所以,那里似乎有些不对劲。

省略一个循环的代码

对于所有有丰富经验的人来说:这绝对可以进一步改进 and/or 可以采用不同的结构。此代码使用与原始代码相同的方法参数,并产生与原始代码相同的测试结果 post。我没有尝试解释缺少使用密钥(DUDE)。

import java.util.Arrays;
class Scratch {
    public static void main(String[] args) {
        Cipher c = new Cipher();
        c.tests();
    }
}
class Cipher {
    public String encode(String textraw, String key) {
        StringBuilder resultString = new StringBuilder();
        Integer[] numbers = {0, 3, 1, 2};
        //split your textraw into substrings of 4
        String[] splitString = textraw.split("(?<=\G.{"+numbers.length+"})");
        for(int i = 0; i < numbers.length; i++){
            //get the index of the number I in your numbers array
            int foundIndex = Arrays.asList(numbers).indexOf(i);
            //should give 0,2,3,1 in the loop
            for(int k = 0; k < splitString.length; k++){
                //get the foundIndex from all substrings in splitStrings and add to the stringbuilder
                //you are looking for splitStrings[k].charAt(foundIndex)
                if(foundIndex < splitString[k].length()){
                    //This avoids errors when the last string is shorter than the maximum chars
                    resultString.append(splitString[k].charAt(foundIndex));
                }
            }
        }
        return resultString.toString();
    }


    public void tests() {
        String input;
        String key;
        input = "hellobro";
        key = "DUDE";
        System.out.println("Encoding " + input + " with key " + key + " gives result: " + encode(input, key));
        input = "dudedude";
        key = "DUDE";
        System.out.println("Encoding " + input + " with key " + key + " gives result: " + encode(input, key));
        input = "abcdabcdabc";
        key = "ABCD";
        System.out.println("Encoding " + input + " with key " + key + " gives result: " + encode(input, key));
    }
}

使用字符串键(DUDE)

您可以添加一个从字符串中获取排序键的方法。 此方法生成一个排序的 ArrayList。 所以你必须制作数字 ArrayList<Integer> numbers = getKeyArray(key); 您必须将 numbers.length 更改为 numbers.size() 并且 foundIndex int foundIndex = numbers.indexOf(i);

方法 getKeyArray 测试

private ArrayList<Integer> getKeyArray(String key) {
        String alfabet = "abcdefghijklmnopqrstuvwxyz";
        ArrayList<Integer> resultArrayList = new ArrayList<>();
        HashMap<Integer, Integer> charRank = new HashMap<>();
        for (int k = 0; k < key.length(); k++) {
             int alfabetIndex = alfabet.indexOf(Character.toLowerCase(key.charAt(k)));
             charRank.put(k, alfabetIndex);
        }
        charRank.entrySet()
                .stream()
                .sorted(Map.Entry.<Integer, Integer>comparingByValue()).forEach(e -> resultArrayList.add(e.getKey()));
        return resultArrayList;
    }

    public void testGetKeyArray() {
        String testInput;

        testInput = "ABDCEFG";
        System.out.println("Test getKeyArray with " + testInput);
        getKeyArray(testInput).forEach(System.out::println);

        testInput = "DUDE";
        System.out.println("Test getKeyArray with " + testInput);
        getKeyArray(testInput).forEach(System.out::println);
    }

输出示例 getKeyArray

"GFEABCD" Result: [3, 4, 5, 6, 2, 1, 0] 
"ABDCEFG" Result: [0, 1, 3, 2, 4, 5, 6]