检查字符串是否包含数组中的字符
Check that string contains a character from array
我想检查作为文件名的字符串是否包含来自 ILLEGAL_CHARACTERS
的非法参数。我可以简单地使用 for 循环,但我想通过 Streams.
来实现
我的代码:
package shared;
import java.util.Arrays;
public class Validator {
private static final Character[] ILLEGAL_CHARACTERS =
{'/','\n','\r','\t','[=10=]','\f','`','?','*','\','<','>','|','\"',':'};
public static boolean fileNameIsValid(String fileName) {
return Arrays.stream(ILLEGAL_CHARACTERS).anyMatch(fileName::contains);
}
}
问题出在包含方法中,因为它需要 CharSequence
而不是 char
。有没有办法在不将 Character[]
类型更改为 String[]
的情况下通过流执行此操作?
你可以尝试使用indexOf
:
return Arrays.stream(ILLEGAL_CHARACTERS)
.map(fileName::indexOf)
.anyMatch(i -> i >= 0);
首先,我建议您使用 Set
而不是数组,因为您不需要为您的内容建立索引,然后流式处理给定字符串中的字符,并检查是否与你的组合有任何匹配。
从字符串的 chars()
方法中获取字符,这将为您提供一个整数数组,然后您可以将其转换为字符“数组”
这就是您所需要的:
private static final Set<Character> ILLEGAL_CHARACTERS = Set.of(
'/','\n','\r','\t','[=10=]','\f','`','?','*','\','<','>','|','\"',':');
public static boolean fileNameIsValid(String fileName) {
return fileName.chars()
.mapToObj(c -> (char) c)
.noneMatch(ILLEGAL_CHARACTERS::contains);
}
Streams 可能不适合这里。此外,现在您的解决方案具有二次复杂性(N*M,其中 N 是文件名长度,M 是非法字符数组的大小),性能不是很好。正如评论中所建议的,您可以使用正则表达式:
private static final Pattern ILLEGAL_CHARACTERS_REGEX =
Pattern.compile("[/\n\r\t[=10=]\f`?*\\<>|\":]");
public static boolean fileNameIsValidRegex(String fileName) {
return !ILLEGAL_CHARACTERS_REGEX.matcher(fileName).find();
}
或者,如果您的非法字符集仅限于 ASCII,您可以尝试使用位集来压缩一些性能:
private static final BitSet ILLEGAL_CHARACTERS = new BitSet();
static {
for (char c : new char[]{
'/','\n','\r','\t','[=11=]','\f','`','?','*','\','<','>','|','\"',':'}) {
ILLEGAL_CHARACTERS.set(c);
}
}
public static boolean fileNameIsValid(String fileName) {
return fileName.chars().noneMatch(ILLEGAL_CHARACTERS::get);
}
如果contains
方法需要一个CharSequence
而不是char
,那么你可以给它:
Arrays.stream(ILLEGAL_CHARACTERS)
.map(String::valueOf)
.anyMatch(fileName::contains);
但在 String
class 的幕后,此方法使用 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);
另请参阅:
我想检查作为文件名的字符串是否包含来自 ILLEGAL_CHARACTERS
的非法参数。我可以简单地使用 for 循环,但我想通过 Streams.
我的代码:
package shared;
import java.util.Arrays;
public class Validator {
private static final Character[] ILLEGAL_CHARACTERS =
{'/','\n','\r','\t','[=10=]','\f','`','?','*','\','<','>','|','\"',':'};
public static boolean fileNameIsValid(String fileName) {
return Arrays.stream(ILLEGAL_CHARACTERS).anyMatch(fileName::contains);
}
}
问题出在包含方法中,因为它需要 CharSequence
而不是 char
。有没有办法在不将 Character[]
类型更改为 String[]
的情况下通过流执行此操作?
你可以尝试使用indexOf
:
return Arrays.stream(ILLEGAL_CHARACTERS)
.map(fileName::indexOf)
.anyMatch(i -> i >= 0);
首先,我建议您使用 Set
而不是数组,因为您不需要为您的内容建立索引,然后流式处理给定字符串中的字符,并检查是否与你的组合有任何匹配。
从字符串的 chars()
方法中获取字符,这将为您提供一个整数数组,然后您可以将其转换为字符“数组”
这就是您所需要的:
private static final Set<Character> ILLEGAL_CHARACTERS = Set.of(
'/','\n','\r','\t','[=10=]','\f','`','?','*','\','<','>','|','\"',':');
public static boolean fileNameIsValid(String fileName) {
return fileName.chars()
.mapToObj(c -> (char) c)
.noneMatch(ILLEGAL_CHARACTERS::contains);
}
Streams 可能不适合这里。此外,现在您的解决方案具有二次复杂性(N*M,其中 N 是文件名长度,M 是非法字符数组的大小),性能不是很好。正如评论中所建议的,您可以使用正则表达式:
private static final Pattern ILLEGAL_CHARACTERS_REGEX =
Pattern.compile("[/\n\r\t[=10=]\f`?*\\<>|\":]");
public static boolean fileNameIsValidRegex(String fileName) {
return !ILLEGAL_CHARACTERS_REGEX.matcher(fileName).find();
}
或者,如果您的非法字符集仅限于 ASCII,您可以尝试使用位集来压缩一些性能:
private static final BitSet ILLEGAL_CHARACTERS = new BitSet();
static {
for (char c : new char[]{
'/','\n','\r','\t','[=11=]','\f','`','?','*','\','<','>','|','\"',':'}) {
ILLEGAL_CHARACTERS.set(c);
}
}
public static boolean fileNameIsValid(String fileName) {
return fileName.chars().noneMatch(ILLEGAL_CHARACTERS::get);
}
如果contains
方法需要一个CharSequence
而不是char
,那么你可以给它:
Arrays.stream(ILLEGAL_CHARACTERS)
.map(String::valueOf)
.anyMatch(fileName::contains);
但在 String
class 的幕后,此方法使用 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);
另请参阅: