我想检查作为文件名的字符串是否包含来自 ILLEGAL_CHARACTERS
的非法参数。我可以简单地使用 for 循环,但我想通过 Streams 来做到这一点。
我的代码:
package shared;
import java.util.Arrays;
public class Validator {
private static final Character[] ILLEGAL_CHARACTERS =
{'/','\n','\r','\t','\0','\f','`','?','*','\\','<','>','|','\"',':'};
public static boolean fileNameIsValid(String fileName) {
return Arrays.stream(ILLEGAL_CHARACTERS).anyMatch(fileName::contains);
}
}
问题出在 contains 方法中,因为它需要一个 CharSequence
而不是 char
。有没有办法通过流来做到这一点,而无需将 Character[]
类型更改为 String[]
?
答案 0 :(得分:5)
Streams 可能不是这里的最佳选择。此外,现在您的解决方案具有二次复杂度(N*M,其中 N 是文件名长度,M 是非法字符数组的大小),性能不是很好。正如评论中所建议的,您可以使用正则表达式:
<!DOCTYPE html>
<html>
<body>
<gcse:search enablehistory="false"></gcse:search>
<gcse:test enablehistory="false"></gcse:test>
<mynamespace:testing enablehistory="false">test</mynamespace:testing>
</body>
</html>
或者,如果您的非法字符集仅限于 ASCII,您可以使用 bitset 来提高性能:
private static final Pattern ILLEGAL_CHARACTERS_REGEX =
Pattern.compile("[/\n\r\t\0\f`?*\\\\<>|\":]");
public static boolean fileNameIsValidRegex(String fileName) {
return !ILLEGAL_CHARACTERS_REGEX.matcher(fileName).find();
}
答案 1 :(得分:3)
您可以尝试使用indexOf
:
return Arrays.stream(ILLEGAL_CHARACTERS)
.map(fileName::indexOf)
.anyMatch(i -> i >= 0);
答案 2 :(得分:2)
首先,我建议你使用 Set
而不是数组,因为你不需要索引你的东西,然后流过给定字符串中的字符,并检查是否有与您的组合的任何匹配。
从字符串的 chars()
方法中获取字符,这将为您提供一个整数数组,然后您可以将其转换为字符“数组”
这里有你需要的一切:
private static final Set<Character> ILLEGAL_CHARACTERS = Set.of(
'/','\n','\r','\t','\0','\f','`','?','*','\\','<','>','|','\"',':');
public static boolean fileNameIsValid(String fileName) {
return fileName.chars()
.mapToObj(c -> (char) c)
.noneMatch(ILLEGAL_CHARACTERS::contains);
}
答案 3 :(得分:0)
如果 contains
方法需要一个 CharSequence
而不是 char
,那么您可以给它:
Arrays.stream(ILLEGAL_CHARACTERS)
.map(String::valueOf)
.anyMatch(fileName::contains);
但是在 String
类中,这个方法使用了 indexOf(String str)
方法:
public boolean contains(CharSequence s) {
return indexOf(s.toString()) > -1;
}
所以,为了避免多余的类型转换,你可以使用另一个indexOf(int ch)
方法:
Arrays.stream(ILLEGAL_CHARACTERS).anyMatch(ch -> fileName.indexOf(ch) > -1);