提问人:Evgeniy 提问时间:6/6/2022 最后编辑:Alexander IvanchenkoEvgeniy 更新时间:6/7/2022 访问量:154
Codingbat 挑战:使用 Stream API 的 mirrorEnds
Codingbat challenge: mirrorEnds using Stream API
问:
给定 CodingBat 的任务 mirrorEnds:
给定一个字符串,在两个字符串中查找镜像(向后)字符串 给定字符串的开头和结尾。
换言之,零或 在给定字符串的开头有更多字符,并且在 字符串的末尾以相反的顺序排列(可能重叠)。为 例如,字符串的 Mirror End 是 。
"abXYZba"
"ab"
例子:
mirrorEnds("abXYZba") → "ab"
mirrorEnds("abca") → "a"
mirrorEnds("aba") → "aba"
我对此任务的解决方案如下:
public String mirrorEnds(String str) {
String result = "";
if (str.length() % 2 != 0) {
for (int i = 0; i < str.length() / 2; i++) {
if (str.charAt(i) == str.charAt(str.length() - i - 1)) {
result += "" + str.charAt(i);
} else {
break;
}
}
if (result.length() == str.length() / 2) {
String strEnd = new StringBuilder(result).reverse().toString();
result += "" + str.charAt(str.length() / 2) + strEnd;
}
}
if (str.length() % 2 == 0) {
for (int i = 0; i < str.length() / 2; i++) {
if (str.charAt(i) == str.charAt(str.length() - i - 1)) {
result += "" + str.charAt(i);
} else {
break;
}
}
if (result.length() == str.length() / 2) {
String strEnd = new StringBuilder(result).reverse().toString();
result += strEnd;
}
}
return result;
}
是否可以使用 Stream API 解决这个问题?
答:
我认为 Stream API 不会给你带来任何优势。但是,您可以像这样优化代码
public String mirrorEnds(String string) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == string.charAt(string.length() - i - 1)) {
result.append(string.charAt(i));
} else {
break;
}
}
return result.toString();
}
评论
for(int i = 0; i < string.length(); i++) { if(string.charAt(i) != string.charAt(string.length() - i - 1)) return string.substring(0, i); } return string;
由于您特意要求此问题的流解决方案,因此这可能是寻找第一个字符与最后一个反转的字符匹配的最大索引,从开始并通过递减继续,直到达到 0。i
i
i
i
length() / 2
i
仅当给定的字符串不是回文时,才应用以前的算法。事实上,在这种情况下,字符串本身可以立即返回。
public static String mirrorEnds(String str) {
if (str.equals(new StringBuilder(str).reverse().toString())) {
return str;
}
OptionalInt maxLen = IntStream.iterate(str.length() / 2, i -> i >= 0, i -> i - 1)
.filter(i -> str.substring(0, i).equals((new StringBuilder(str.substring(str.length() - i))).reverse().toString()))
.max();
return maxLen.isPresent() ? str.substring(0, maxLen.getAsInt()) : null;
}
输出
ab
a
aba
下面是测试代码的链接:
https://www.jdoodle.com/iembed/v0/rUL
它可以在单个流语句中实现。IntStream.range()
为了创建一个单行代码,我们需要 的帮助,这是在 Java 9 中引入的。 是一种所谓的短 cercuit 操作,即它将在与给定谓词不匹配的第一个元素之后中断。takeWhile()
takeWhile()
public static String mirrorEnds(String str) {
return IntStream.range(0, str.length())
.takeWhile(i -> str.charAt(i) == str.charAt(str.length() - 1 - i))
.map(str::codePointAt)
.collect(StringBuilder::new,
StringBuilder::appendCodePoint,
StringBuilder::append)
.toString();
}
由于 CodingBat 仍在 Java 8 上,它的编译器会抱怨上面的代码。
@Holger 提出的一个非常好的、符合 Java 8 的简单解决方案。
它查找开头和结尾字符之间第一个不匹配的索引,并生成一个从开头到索引的子字符串。0
mismatch
如果返回一个空的可选字符串,即给定的字符串是回文并且没有不匹配,则给定字符串的长度将通过 提供。findFirst()
orElse()
下面的代码通过了 CodingBat 上的所有测试。
public String mirrorEnds(String str) {
int mismatch = IntStream.range(0, str.length() / 2)
.filter(i -> str.charAt(i) != str.charAt(str.length() - 1 - i))
.findFirst()
.orElse(str.length());
return str.substring(0, mismatch);
}
注意,由于 CodingBat 不允许导入,为了在本站点上运行上述代码,您需要使用所谓的类的完全限定名称。java.util.stream.IntStream
评论
return str.substring(0, IntStream.range(0, str.length()) .filter(i -> str.charAt(i) != str.charAt(str.length() - 1 - i)) .findFirst().orElse(str.length()));
range(0, str.length())
range(0, str.length() / 2)
评论