首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java语言中的Morse代码翻译

Java语言中的Morse代码翻译
EN

Code Review用户
提问于 2017-04-30 22:26:24
回答 1查看 3.7K关注 0票数 3

我正在使用Maven在Java中编写一个名为"Learn“的应用程序。莫尔斯代码翻译是这个应用程序的一部分。我创建了编码和解码方法来翻译莫尔斯代码,并将HashMap移到属性文件中。我还创建了一个按值获取键的助手方法。

pl/hubot/dev/learn_morse/model/Encoder.java:

代码语言:javascript
复制
package pl.hubot.dev.learn_morse.model;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

public class Encoder {
    public final String encode(final String input)
            throws IOException,
            NoSuchFieldException {
        StringBuilder encoded = new StringBuilder();
        String lowerCaseInput = input.toLowerCase();
        for (int i = 0; i < lowerCaseInput.length(); i++) {
            char current = lowerCaseInput.charAt(i);
            encoded.append(getMorseCode().getOrDefault(
                    Character.toString(current), " "));
            encoded.append("   ");
        }
        return encoded.toString();
    }

    public final String decode(final String input)
            throws IOException,
            NoSuchFieldException {
        StringBuilder decoded = new StringBuilder();
        String lowerCaseInput = input.toLowerCase();
        for (String current : lowerCaseInput.split(" ")) {
            String key = getKeyByValue(getMorseCode(), current);
            if (key != null) {
                decoded.append(key);
            }
            decoded.append(" ");
        }
        return decoded.toString();
    }

    final Map<String, String> getMorseCode()
            throws IOException,
            NoSuchFieldException {
        Class<?> aClass = Encoder.class;
        ClassLoader classLoader = aClass.getClassLoader();
        String filename = "morse_code.properties";
        try (InputStream input = classLoader
                .getResourceAsStream(filename)) {
            if (input == null) {
                throw new FileNotFoundException(
                        "Sorry, unable to find "
                                + filename);
            }

            Properties properties = new Properties();
            properties.load(input);

            Map<String, String> translations = new HashMap<>();
            for (String key : properties.stringPropertyNames()) {
                String value = properties.getProperty(key);
                translations.put(key, value);
            }

            return translations;
        }
    }

    private <T, E> T getKeyByValue(final Map<T, E> map, final E value) {
        for (Map.Entry<T, E> entry : map.entrySet()) {
            if (Objects.equals(value, entry.getValue())) {
                return entry.getKey();
            }
        }
        return null;
    }
}

resources/morse_code.properties:

代码语言:javascript
复制
a = ._
b = _...
c = _._.
d = _..
e = .
f = .._.
g = __.
h = ....
i = ..
j = .____
k = _._
l = ._..
m = __
n = _.
o = ___
p = .__.
q = __._
r = ._.
s = ...
t = _
u = .._
v = ..._
w = .__
x = _.._
y = _.__
z = __..
\u0105 = ._._
\u0107 = _._..
\u0119 = .._..
\u00E9 = .._..
ch = ____
\u0142 = ._.._
\u0144 = __.__
\u00F3 = ___.
\u015B = ..._...
\u017A = __.._
\u017C = __.._.
0 = _____
1 = .____
2 = ..___
3 = ...__
4 = ...._
5 = .....
6 = _....
7 = __...
8 = ___..
9 = ____.
. = ._._._
, = __..__
' = .____.
" = ._.._.
_ = ..__._
\: = ___...
; = _._._.
? = ..__..
\! = _._.__
- = _...._
+ = ._._.
/ = _.._.
( = _.__.
) = _.__._
\= = _..._
@ = .__._.
EN

回答 1

Code Review用户

发布于 2017-05-01 00:21:02

简单-ish性能改进:

与其每次调用getMorseCode()时读取morse表,不如将查找表缓存在字段中的实例中:

代码语言:javascript
复制
public class Encoder  {
    private static final Map<Character, String> morseCode = new HashMap<>();

您会注意到,我已经更改了Map的“键”类型。不是将从charAt获得的字符转换为String (创建一个全新的实例和所有类创建开销),而是将char自动装箱为字符,这可能更快,而且通常更干净。

这方面最好的部分是将NoSuchFileExceptionNoSuchFieldException从运行时(和方法签名)移动到应用程序的启动(或者更正确地加载类)。

您可以在静态初始化程序块中初始化映射,如下所示:

代码语言:javascript
复制
static {
    try (InputStream props = Encoder.class.getClassLoader().getResourceAsStream("morse_code.properties")) {
        Properties properties = new Properties(props);
        for (String key : properties.stringPropertyNames()) {
            morseCode.put(key, properties.getProperty(key));
        }
    } 
 }

如果我们稍微斜视一下,我们可以在这里看到与getKeyByValue一起的另一个可能的改进。由于我们预先计算了morse代码的映射,难道我们不能预先计算反向映射并从地图查找时间中受益,而不是在得到我们想要的东西之前搜索所有的值:

代码语言:javascript
复制
private static final Map<String, Character> reverseMorseCode = new HashMap<>();

现在,我们可以使用以下方法扩展静态初始化程序:

代码语言:javascript
复制
for (String key : properties.stringPropertyNames()) {
    String morseCode = properties.getProperty(key);
    morseCode.put(key, morseCode);
    reverseMorseCode.put(morseCode, key);
}

结合这一点将大大加快decode方法的速度。

复杂事物:

让我们从“功能”的角度考虑一下手头的任务。实际上,您拥有的是一个简单的密码,从明文到点破折号密码。我们可以将每个字符上的函数表示为结果空间。我们需要将这个“映射功能”应用于原始输入中的每个字符。

Java在Java 8中引入了一些与此完全相适应的东西: Streams。

可以用流重写encode方法,如下所示:

代码语言:javascript
复制
public final String encode(final String input) {
     return input.chars()
         .mapToObject(c -> morseCode.getOrDefault((char) c, " "))
         .collect(Collectors.joining("   "));
}

这使我们可以直接从“逆函数”的角度来考虑decode

代码语言:javascript
复制
public final String decode(final String input) {
    return Arrays.stream(input.toLowerCase().split(" "))
        .map(token -> reverseMorseCode.getOrDefault(token, " "))
        .collect(Collectors.joining(""));
}

类似的东西存在于从一个文件读取,这将允许我们阅读莫尔斯映射,而不走的方式,Properties。它叫Files.lines

使用Files.lines实现静态初始化器是留给读者的练习;)

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/162195

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档