我正在使用Maven在Java中编写一个名为"Learn“的应用程序。莫尔斯代码翻译是这个应用程序的一部分。我创建了编码和解码方法来翻译莫尔斯代码,并将HashMap移到属性文件中。我还创建了一个按值获取键的助手方法。
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;
}
}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 = ____.
. = ._._._
, = __..__
' = .____.
" = ._.._.
_ = ..__._
\: = ___...
; = _._._.
? = ..__..
\! = _._.__
- = _...._
+ = ._._.
/ = _.._.
( = _.__.
) = _.__._
\= = _..._
@ = .__._.发布于 2017-05-01 00:21:02
与其每次调用getMorseCode()时读取morse表,不如将查找表缓存在字段中的实例中:
public class Encoder {
private static final Map<Character, String> morseCode = new HashMap<>();您会注意到,我已经更改了Map的“键”类型。不是将从charAt获得的字符转换为String (创建一个全新的实例和所有类创建开销),而是将char自动装箱为字符,这可能更快,而且通常更干净。
这方面最好的部分是将NoSuchFileException和NoSuchFieldException从运行时(和方法签名)移动到应用程序的启动(或者更正确地加载类)。
您可以在静态初始化程序块中初始化映射,如下所示:
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代码的映射,难道我们不能预先计算反向映射并从地图查找时间中受益,而不是在得到我们想要的东西之前搜索所有的值:
private static final Map<String, Character> reverseMorseCode = new HashMap<>();现在,我们可以使用以下方法扩展静态初始化程序:
for (String key : properties.stringPropertyNames()) {
String morseCode = properties.getProperty(key);
morseCode.put(key, morseCode);
reverseMorseCode.put(morseCode, key);
}结合这一点将大大加快decode方法的速度。
让我们从“功能”的角度考虑一下手头的任务。实际上,您拥有的是一个简单的密码,从明文到点破折号密码。我们可以将每个字符上的函数表示为结果空间。我们需要将这个“映射功能”应用于原始输入中的每个字符。
Java在Java 8中引入了一些与此完全相适应的东西: Streams。
可以用流重写encode方法,如下所示:
public final String encode(final String input) {
return input.chars()
.mapToObject(c -> morseCode.getOrDefault((char) c, " "))
.collect(Collectors.joining(" "));
}这使我们可以直接从“逆函数”的角度来考虑decode:
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实现静态初始化器是留给读者的练习;)
https://codereview.stackexchange.com/questions/162195
复制相似问题