用 Java 中的 LinkedHashMap 替换 StringBuilder 中的字符

Replacing characters in StringBuilder with LinkedHashMap in Java

基本上我正在编写一个程序,它接收一大段文本(比如一篇文章),并根据接收到程序中的另外两个字符串行替换字符,如下所示:

uvxftkbsqpznlcwdeijhoamgyr

etaoinsrhldcumfpgwybvkxjqz

程序遍历大文本块中的字符,如果一个字符与最上面几行字符匹配,它会用下面的字符替换它。 我已将两个字符串行放入 LinkedHashMap 以便于访问,但由于某种原因,程序没有正确替换字符。这是我的代码:

public class MyReplacer{

public static void main(String[] args) throws IOException {
    String fileName = "";
    Scanner in = new Scanner(System.in);
    System.out.println("Please enter file name");
    fileName = in.nextLine();
    BufferedReader readerForText = new BufferedReader(new FileReader(fileName));
    Scanner keyFileReader = new Scanner(new File("Key.txt"));
    String topLine = "";
    String bottomLine = "";
    //BufferedReader readerForKeyFile = new BufferedReader(new FileReader("Key.java"));
    StringBuilder fileString = new StringBuilder();

    List<Character> topList = new ArrayList<Character>();

    List<Character> bottomList = new ArrayList<Character>();

    try{
         String line = readerForText.readLine();
         while (line!= null){
             fileString.append(line);
             fileString.append("\n");
             line = readerForText.readLine();
         }
         fileString.toString().toLowerCase();

         System.out.println(fileString);
         topLine = keyFileReader.nextLine();
         bottomLine = keyFileReader.nextLine();


         //Convert top line to char array
         char arrayChar1[] = topLine.toCharArray();
         for(char a:arrayChar1)
         {
            topList.add(a);
         }

         //Convert bottom to char array
         char arrayChar2[] = bottomLine.toCharArray();
         for(char a:arrayChar2)
         {
            bottomList.add(a);
         }


         LinkedHashMap<Character,Character> keyMapper = new LinkedHashMap<Character,Character>();

         for(int i = 0;i<topLine.length();++i)
         {
             keyMapper.put(arrayChar1[i],arrayChar2[i]);
         }

         //Testing that key and value pair has been read in correctly
             for(Map.Entry<Character, Character> entry : keyMapper.entrySet())
                {
                    System.out.print(entry.getKey()+  "\n" + entry.getValue());
                }


         //Replace letters in fileString

            for(int x = 0;x<fileString.length();x++)
            {
                for(Map.Entry<Character, Character> entry : keyMapper.entrySet())
                {
                    if(fileString.charAt(x)==entry.getKey())
                    {
                        fileString.setCharAt(x,entry.getValue());
                    }

                }
            }
System.out.println(fileString);



     } finally{
         readerForText.close();
         keyFileReader.close();
 }
}

大文本的示例如下所示:

vkpuu mlusvbxfs

然而,当我替换字符时,它看起来像:

wxujj xujzwzkvz

因此没有正确替换字符

任何关于为什么这样做的解释都很好。 谢谢

问题就出在这里

for(int x = 0;x<fileString.length();x++)
{
    for(Map.Entry<Character, Character> entry : keyMapper.entrySet())
    {
        if(fileString.charAt(x)==entry.getKey())
        {
            fileString.setCharAt(x,entry.getValue());
        }

    }
}      

这应该是

for(int x = 0;x<fileString.length();x++)
{
    Character c = keyMapper.get(fileString.charAt(x));
    if (c != null)
        fileString.setCharAt(x, c);
}

你的方法的问题在于,通过像这样搜索条目,你可以多次更改单个字符。

例如

u -> e -> g -> j

为什么你没有得到正确的答案? 因为这有一个内循环:

   for (Map.Entry<Character, Character> entry : keyMapper.entrySet()) {
        if (fileString.charAt(x) == entry.getKey()) {
             fileString.setCharAt(x, entry.getValue());
         }
    }

考虑 x = 0 处的第一个字母,首先将 v 替换为 t,然后将 t 替换为 i 等, 所以你可以修改为:

for (Map.Entry<Character, Character> entry : keyMapper.entrySet()) {
 if (fileString.charAt(x) == entry.getKey()) {
     fileString.setCharAt(x, entry.getValue());
     //not need to continue find
     break;
   }

}

或更简单:

for (int x = 0; x < fileString.length(); x++) {
            if (keyMapper.containsKey(fileString.charAt(x))) {
                fileString.setCharAt(x,     keyMapper.get(fileString.charAt(x)));
            }
        }

你把事情复杂化了。不要填充 StringBuilder 然后替换字符(只需添加字符),不要创建不必要的变量,不要不必要地循环。

试试这个:

Map<Character, Character> map = new HashMap<>();
for (int i = 0; i < topLine.length(); i++)
    map.put(topLine.charAt(i), bottomLine.charAt(i));
String line = readerForText.readLine();
StringBuilder fileString = new StringBuilder();
for (char c : line.toCharArray())
    fileString.append(map.get(c));
System.out.println(fileString);