1. 概述
摩尔斯电码通过点和划的组合来表示字母、数字和标点符号。由塞缪尔·摩尔斯和阿尔弗雷德·维尔在1830年代早期为电报通信开发。
本教程将实现英文到摩尔斯电码的转换方法,以及反向转换方法。
2. 编写摩尔斯电码
2.1 摩尔斯电码基础
摩尔斯电码中,每个字符由短信号(点)和长信号(划)的唯一组合表示。我们使用 .
表示点,-
表示划。但仅用这两个字符无法完整表示句子。
摩尔斯电码通信中,字符间的短暂停顿和单词间的较长停顿至关重要。我们采用以下约定:
- 字符间用空格分隔
- 单词间用
/
表示(前后需加空格)
2.2 英文与摩尔斯电码的双向映射
为实现双向转换,我们需要建立英文与摩尔斯电码的双向映射关系。使用 Apache Commons Collections 的 BidiMap
数据结构,它支持通过键或值访问。若只需单向转换,直接使用 Map
即可。
首先在 pom.xml
中添加依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
创建映射类并初始化:
public class MorseTranslator {
private static final BidiMap<String, String> morseAlphabet = new DualHashBidiMap<>();
static {
morseAlphabet.put("A", ".-");
morseAlphabet.put("B", "-...");
morseAlphabet.put("C", "-.-.");
morseAlphabet.put("D", "-..");
morseAlphabet.put("E", ".");
morseAlphabet.put("F", "..-.");
morseAlphabet.put("G", "--.");
morseAlphabet.put("H", "....");
morseAlphabet.put("I", "..");
// 等等...
morseAlphabet.put(" ", "/");
}
}
⚠️ 注意:
- 映射表只包含大写字母(转换时统一转为大写)
- 空格字符已特殊处理
- 重音字符(如 à, å)可能对应相同摩尔斯码,需特殊处理
3. 将英文翻译为摩尔斯电码
3.1 核心算法
转换步骤:统一转为大写 → 逐字符翻译 → 用空格拼接:
static String englishToMorse(String english) {
String upperCaseEnglish = english.toUpperCase();
String[] morse = new String[upperCaseEnglish.length()];
for (int index = 0; index < upperCaseEnglish.length(); index++) {
String morseCharacter = morseAlphabet.get(String.valueOf(upperCaseEnglish.charAt(index)));
morse[index] = morseCharacter;
}
return String.join(" ", morse);
}
使用参数化测试验证大小写不敏感:
@ParameterizedTest
@ValueSource(strings = {"MORSE CODE!", "morse code!", "mOrSe cOdE!"})
void givenAValidEnglishWordWhateverTheCapitalization_whenEnglishToMorse_thenTranslatedToMorse(String english) {
assertEquals("-- --- .-. ... . / -.-. --- -.. . -.-.-----.", MorseTranslator.englishToMorse(english));
}
3.2 边界情况处理
需拒绝包含非法字符的输入,抛出 IllegalArgumentException
:
static String englishToMorse(String english) {
if (english == null) {
return null;
}
String upperCaseEnglish = english.toUpperCase();
String[] morse = new String[upperCaseEnglish.length()];
for (int index = 0; index < upperCaseEnglish.length(); index++) {
String morseCharacter = morseAlphabet.get(String.valueOf(upperCaseEnglish.charAt(index)));
if (morseCharacter == null) {
throw new IllegalArgumentException("Character " + upperCaseEnglish.charAt(index) + " can't be translated to morse");
}
morse[index] = morseCharacter;
}
return String.join(" ", morse);
}
测试非法字符场景:
@Test
void givenAnEnglishWordWithAnIllegalCharacter_whenEnglishToMorse_thenThrows() {
String english = "~This sentence starts with an illegal character";
assertThrows(IllegalArgumentException.class, () -> MorseTranslator.englishToMorse(english));
}
4. 将摩尔斯电码翻译为英文
4.1 核心算法
转换步骤:按空格分割摩尔斯字符 → 逐个反向查询 → 拼接结果:
static String morseToEnglish(String morse) {
String[] morseUnitCharacters = morse.split(" ");
StringBuilder stringBuilder = new StringBuilder();
for (int index = 0; index < morseUnitCharacters.length; index ++) {
String englishCharacter = morseAlphabet.getKey(morseUnitCharacters[index]);
stringBuilder.append(englishCharacter);
}
return stringBuilder.toString();
}
验证转换结果:
@Test
void givenAValidMorseWord_whenMorseToEnglish_thenTranslatedToUpperCaseEnglish() {
assertEquals("MORSE CODE!", MorseTranslator.morseToEnglish("-- --- .-. ... . / -.-. --- -.. . -.-.-----."));
}
✅ 输出始终为大写字母
4.2 边界情况处理
需处理三种异常情况:
null
输入- 空字符串(
split()
方法特殊行为) - 非法摩尔斯字符
最终实现:
static String morseToEnglish(String morse) {
if (morse == null) {
return null;
}
if (morse.isEmpty()) {
return "";
}
String[] morseUnitCharacters = morse.split(" ");
StringBuilder stringBuilder = new StringBuilder();
for (int index = 0; index < morseUnitCharacters.length; index ++) {
String englishCharacter = morseAlphabet.getKey(morseUnitCharacters[index]);
if (englishCharacter == null) {
throw new IllegalArgumentException("Character " + morseUnitCharacters[index] + " is not a valid morse character");
}
stringBuilder.append(englishCharacter);
}
return stringBuilder.toString();
}
测试非法摩尔斯字符:
@Test
void givenAMorseWordWithAnIllegalCharacter_whenMorseToEnglish_thenThrows() {
assertThrows(IllegalArgumentException.class, () -> MorseTranslator.morseToEnglish(".!!!!!!!"));
}
5. 总结
本文实现了摩尔斯电码与英文的双向转换器。核心要点:
- 使用
BidiMap
维护双向映射 - ✅ 正确处理字符/单词分隔符
- ❌ 严格校验非法输入
- 💡 可扩展为通用语言转换框架
完整代码见 GitHub 仓库。