简体   繁体   English

检查字符串是否包含数组中的字符

[英]Check that string contains a character from array

I would like to check that string that is a filename contains a illegal argument from the ILLEGAL_CHARACTERS .我想检查作为文件名的字符串是否包含来自ILLEGAL_CHARACTERS的非法参数。 Simply I could use for loop, but I want to do this by Streams .我可以简单地使用 for 循环,但我想通过Streams来做到这一点。

My code:我的代码:

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);
    }
}

Problem is in contains method cuz It needs a CharSequence instead of char .问题在于 contains 方法因为它需要一个CharSequence而不是char Is there any way to do this by stream without changing Character[] type to String[] ? stream 有什么方法可以做到这一点,而无需将Character[]类型更改为String[]

Streams might not the best fit here. Streams 在这里可能不是最合适的。 Also, now your solution has quadratic complexity (N*M, where N is the file name length, and M is the size of your illegal character array), which is not very performant.此外,现在您的解决方案具有二次复杂度(N*M,其中 N 是文件名长度,M 是非法字符数组的大小),性能不是很好。 As proposed in the comments, you could use a regular expression:正如评论中所建议的,您可以使用正则表达式:

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();
}

Or, if your illegal character set is limited to ASCII, you could play around with a bitset to squeeze some performance:或者,如果您的非法字符集仅限于 ASCII,您可以使用 bitset 来提高性能:

private static final BitSet ILLEGAL_CHARACTERS = new BitSet();

static {
    for (char c : new char[]{
            '/','\n','\r','\t','\0','\f','`','?','*','\\','<','>','|','\"',':'}) {
        ILLEGAL_CHARACTERS.set(c);
    }
}

public static boolean fileNameIsValid(String fileName) {
    return fileName.chars().noneMatch(ILLEGAL_CHARACTERS::get);
}

You can try to use indexOf :您可以尝试使用indexOf

return Arrays.stream(ILLEGAL_CHARACTERS)
             .map(fileName::indexOf)
             .anyMatch(i -> i >= 0);

First, I would recommend that you use a Set instead of an array, because you don't have any need for indexing your stuff, then Stream over the characters from the given string, and check if there is any match with your set.首先,我建议您使用Set而不是数组,因为您不需要索引您的东西,然后 Stream 覆盖给定字符串中的字符,并检查是否与您的集合匹配。

Get the chars from the chars() method on a string, this will give you a array of integeres, which you then can cast to an char "array"从字符串上的chars()方法获取字符,这将为您提供一个整数数组,然后您可以将其转换为一个字符“数组”

Here's all you need:这就是你所需要的:

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);
}

If contains method needs a CharSequence instead of char , then you can give it to it :如果contains方法需要一个CharSequence而不是char ,那么你可以给它

Arrays.stream(ILLEGAL_CHARACTERS)
        .map(String::valueOf)
        .anyMatch(fileName::contains);

But under the hood in the String class, this method uses indexOf(String str) method:但在String class 的内部,此方法使用indexOf(String str)方法:

public boolean contains(CharSequence s) {
    return indexOf(s.toString()) > -1;
}

So, to avoid redundant type conversion, you can use another indexOf(int ch) method:所以,为了避免多余的类型转换,你可以使用另一个indexOf(int ch)方法:

Arrays.stream(ILLEGAL_CHARACTERS).anyMatch(ch -> fileName.indexOf(ch) > -1);

See also: How to “subtract” 2 given strings In Java?另请参阅:如何在 Java 中“减去”2 个给定的字符串?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM