Java 使用Lambda表达式使用HashMap替换字符串中的字符
所以我正在做一个项目,在这个项目中,我必须将一个包含希腊字母的字符串转换成一个包含这个字母的英语表示形式的字符串。因此,希腊语Java 使用Lambda表达式使用HashMap替换字符串中的字符,java,lambda,Java,Lambda,所以我正在做一个项目,在这个项目中,我必须将一个包含希腊字母的字符串转换成一个包含这个字母的英语表示形式的字符串。因此,希腊语α将变成α,Α将变成α 我创建了一个HashMap,它具有从Unicode字符到普通字符串的适当转换 我使用了一个简单的For循环来检查输入String中的Char是否是HashMap中的键,如果是,我将使用StringBuilder附加其替换项。以下是我用于执行此操作的代码: char[] ca = snippet.toCharArray(); Stri
α
将变成α
,Α
将变成α
我创建了一个HashMap,它具有从Unicode字符到普通字符串的适当转换
我使用了一个简单的For
循环来检查输入String
中的Char
是否是HashMap
中的键,如果是,我将使用StringBuilder
附加其替换项。以下是我用于执行此操作的代码:
char[] ca = snippet.toCharArray();
StringBuilder out = new StringBuilder();
for (char c : ca) {
if (GREEK_LETTER_DICT.containsKey(Character.toString(c))) {
out.append( GREEK_LETTER_DICT.get(Character.toString(c)));
} else {
out.append(c);
}
}
return out.toString();
这是一个公共静态方法,以String
作为输入。
我想知道的是,是否可以对lambda表达式执行相同的操作?我已经在字符串中找到了一些替代字符的解决方案,但它们不使用HashMap
/字典
我明白为了使用lambda表达式而将其转换为lambda表达式是完全没有用的,但是因为我还有另外7个函数将我的代码缩短了近60%,我想看看是否有可能在“一行”代码中实现这一点。通过这种方式,我可以减少使用的单独方法的数量,并获得更干净的代码
到目前为止,我已经找到了一种将字符串
转换为流
的方法,使用:
String.chars()
然后使用将此IntStream
转换为流
.mapToObj(ch -> (char) ch)
.filter(ch -> (GREEK_LETTER_DICT.containsKey(ch)))
并进行过滤,以查看字符是否位于哈希映射中
.mapToObj(ch -> (char) ch)
.filter(ch -> (GREEK_LETTER_DICT.containsKey(ch)))
问题在于我不能做到这一点
如果原始字符
不在哈希映射
将字符
替换为哈希映射中的字符串
因此,在这两点上的任何帮助都是非常感谢的。我发现,有时我的想法是错误的,因为我不应该查看字符串中的字符是否等于选项列表中的字符,而是应该检查该选项列表是否返回正的索引。所以这个(伪代码):
“StringWithOptions.indexOf('characterLiteral')
与此相反:
Character.equals(“其中一个”)
我会这样做:
str
.chars()
.forEach(
character -> out.append(
GREEK_LETTER_DICT.getOrDefault(Character.toString(c), c)
)
);
因此,使用来自的代码,我能够让它工作。生成的代码现在返回一个字符串
,返回正确的结果,并通过所有单元测试
这是生成的代码:
return snippet.chars()
.mapToObj(c -> (char) c)
.collect(Collector.of(StringBuilder::new,
(stringBuilder, c) -> stringBuilder.append(GREEK_LETTER_DICT.getOrDefault(c,c.toString())),
StringBuilder::append,
StringBuilder::toString));
来自的代码有一个问题,HashMap
使用
,而不是
。因此,我必须更改#getOrDefault
的参数。将它与.mapToObj(c->(char)c)
结合使用,就成功了
现在让我们看看我是否可以改变这一点:
(stringBuilder, c) -> stringBuilder.append(GREEK_LETTER_DICT.getOrDefault(c,c.toString())),
StringBuilder::append
类似于StringBuilder::append(希腊文字母DICT.getOrDefault(c,Character.toString(c))
如何:
public static String replaceGreekLetters(String snippet) {
return snippet
.chars()
.mapToObj(c -> (char) c)
.map(c -> GREEK_LETTER_DICT.getOrDefault(c, c.toString()))
.collect(Collectors.joining());
}
使用蒸汽有几种很好的解决方案。我更喜欢简单的方案:
- 避免从字符到字符串的转换
- 避免在流管道之外使用StringBuffer
- 使用预定义收集器
基于所讨论的代码str.chars().forEach(character->out.append(希腊文字母_DICT.getOrDefault(character.toString(c),c));
很快;-)感谢您的回复。有了这段代码,我们就可以让它工作了。我会把它挂在这里。我不得不对代码做一些修改。我建议你把这句话写进答案里。map
不是更好吗?这样OP就根本不需要StringBuilder了?这只是使用streams的借口。如果每个循环都将是有状态的,则对其使用法线。这比操作状态变量(Stringbuilder)要好,它提供了更好的并行性:)@niceman此过滤器可以并行执行。您建议不要使用StringBuilder
吗?@NathanvanDalen是的,如果不将c.toString()
添加到getOrDefault
的第一个参数中,我将无法实现此功能。我认为mapToObj
应该映射到String
@4Castle我的首字母TS包含一个错误,其中希腊文字母containsKey(Character.toString(c))
应该是希腊文字母containsKey(c)
,因为HashMap是,但我忘了更改它@xehpuk的代码是正确的。OP使用的是Map
。好的解决方案!但是这个线程安全吗?我想这是因为String
本身就是。这确实是一个非常优雅的解决方案,只需3行代码。与我之前的10行相比,可读性有很大的不同@4castle:我可以轻松切换回
。@NathanvanDalen是的,它是线程安全的。它的功能与其他解决方案非常相似。您可以使用Pattern.compile(“”).splitAsStream(original)
而不是Arrays.stream(original.split(“”))来避免创建临时数组。MuttoObj[cto>字符> toStand((char)c)效率更高……你认为这比你原来的循环短/简单吗?