如何使用哈希图将字符设置为不同的字符?
How to use a hashmap to set characters equal to different characters?
对于我的 compsci class 中的作业,我需要使用哈希映射将消息转换为加密消息。我们被告知通过将给定消息字符串中的所有字符替换为替换字母表中的字符来执行此操作,替换字母表由从 a 到 z[=32= 的小写字母组成].此外,替换应按字母顺序进行。
例如,如果我们收到消息“hello”,我们的密码应该将 h 映射到 a,e 到 b,l 到 c,以及 o 到 d,给我们字符串 abccd。从理论上讲,这似乎并不难,但我在实际转换字符时遇到了很多麻烦。我已经在我打算进行实际转换的地方发表了评论,但到目前为止,我得到的只是一堆 a 和 b的放在一起。我在这里做错了什么?
在此先感谢您的帮助。
编辑:由于@taha
删除了一些冗余代码
public class Encryption {
public String encrypt(String message) {
StringBuilder convertedMessage = new StringBuilder();
int counter = 0;
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
HashMap<Character, Character> converter = new HashMap<>();
String messageholder = message.toLowerCase();
char[] charMessage = messageholder.toCharArray();
//this statement is what's giving me an aneurysm
for (char i : charMessage ) {
converter.putIfAbsent(i, alphabet[counter]);
counter++;
}
for (Character c : converter.keySet()) {
char value = converter.get(c);
convertedMessage.append(value);
}
return convertedMessage.toString();
}
}
代码似乎有 2 个主要问题:
- 试图从输入消息中删除非字母字符
- 根本不需要第二个循环,一旦选择了密码字符,就应该在迭代输入消息的同时构建加密消息。
public static String encrypt(String message){
StringBuilder convertedMessage = new StringBuilder();
int counter = 0;
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
HashMap<Character, Character> converter = new HashMap<>();
// keep only lower-case English letters
message = message.replaceAll("[^A-Za-z]", "").toLowerCase();
for (char i : message.toCharArray()) {
converter.putIfAbsent(i, alphabet[counter++]);
convertedMessage.append(converter.get(i));
}
return convertedMessage.toString();
}
// Test
System.out.println(encrypt("Hello,World!"));
输出:
abccefehcj
但是,每次从输入消息中查找一个字符时,上面的代码 都会更新计数器 ,因此可能会跳过一些值。例如,d
被跳过,因为 counter
在 hello
中的第二个 l
递增。类似地,g
在 world
中第二次出现 o
时被跳过,等等
因此,使用方法 Map::computeIfAbsent
而不是 Map::putIfAbsent
是有意义的,它只在需要时调用一个函数来修改计数器。
在这种情况下,counter
应作为有效的最终变量实现,因为它在 lambda 函数中使用 - 作为数组或 AtomicInteger
:
int[] counter = new int[1]; // or AtomicInteger counter = new AtomicInteger();
for (char i : charMessage ) {
converter.computeIfAbsent(i, k -> alphabet[counter[0]++]);
// for AtomicInteger converter.computeIfAbsent(i, k -> alphabet[counter.getAndIncrement()]);
convertedMessage.append(converter.get(i));
}
然后 Hello World!
的加密字符串如下所示:
abccdedfcg
对于我的 compsci class 中的作业,我需要使用哈希映射将消息转换为加密消息。我们被告知通过将给定消息字符串中的所有字符替换为替换字母表中的字符来执行此操作,替换字母表由从 a 到 z[=32= 的小写字母组成].此外,替换应按字母顺序进行。
例如,如果我们收到消息“hello”,我们的密码应该将 h 映射到 a,e 到 b,l 到 c,以及 o 到 d,给我们字符串 abccd。从理论上讲,这似乎并不难,但我在实际转换字符时遇到了很多麻烦。我已经在我打算进行实际转换的地方发表了评论,但到目前为止,我得到的只是一堆 a 和 b的放在一起。我在这里做错了什么?
在此先感谢您的帮助。
编辑:由于@taha
删除了一些冗余代码public class Encryption {
public String encrypt(String message) {
StringBuilder convertedMessage = new StringBuilder();
int counter = 0;
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
HashMap<Character, Character> converter = new HashMap<>();
String messageholder = message.toLowerCase();
char[] charMessage = messageholder.toCharArray();
//this statement is what's giving me an aneurysm
for (char i : charMessage ) {
converter.putIfAbsent(i, alphabet[counter]);
counter++;
}
for (Character c : converter.keySet()) {
char value = converter.get(c);
convertedMessage.append(value);
}
return convertedMessage.toString();
}
}
代码似乎有 2 个主要问题:
- 试图从输入消息中删除非字母字符
- 根本不需要第二个循环,一旦选择了密码字符,就应该在迭代输入消息的同时构建加密消息。
public static String encrypt(String message){
StringBuilder convertedMessage = new StringBuilder();
int counter = 0;
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
HashMap<Character, Character> converter = new HashMap<>();
// keep only lower-case English letters
message = message.replaceAll("[^A-Za-z]", "").toLowerCase();
for (char i : message.toCharArray()) {
converter.putIfAbsent(i, alphabet[counter++]);
convertedMessage.append(converter.get(i));
}
return convertedMessage.toString();
}
// Test
System.out.println(encrypt("Hello,World!"));
输出:
abccefehcj
但是,每次从输入消息中查找一个字符时,上面的代码 都会更新计数器 ,因此可能会跳过一些值。例如,d
被跳过,因为 counter
在 hello
中的第二个 l
递增。类似地,g
在 world
中第二次出现 o
时被跳过,等等
因此,使用方法 Map::computeIfAbsent
而不是 Map::putIfAbsent
是有意义的,它只在需要时调用一个函数来修改计数器。
在这种情况下,counter
应作为有效的最终变量实现,因为它在 lambda 函数中使用 - 作为数组或 AtomicInteger
:
int[] counter = new int[1]; // or AtomicInteger counter = new AtomicInteger();
for (char i : charMessage ) {
converter.computeIfAbsent(i, k -> alphabet[counter[0]++]);
// for AtomicInteger converter.computeIfAbsent(i, k -> alphabet[counter.getAndIncrement()]);
convertedMessage.append(converter.get(i));
}
然后 Hello World!
的加密字符串如下所示:
abccdedfcg