如何检查一个字符串是否包含两个星号字符?

11
我们有一个字符串输入,以下组合是有效的(例如 sunday*sunday*sun*day**sun*daysu*nda*y)。如果仅包含一个星号,则为坏输入。
因此,给定上述输入,如何检查字符串是否包含多个星号。

它应该恰好是两个。 - Achaius
6个回答

9
int asterisk1 = input.indexOf('*');
boolean hasTowAsterisks = asterisk1 != -1 && input.indexOf('*', asterisk1+1) != -1;

编辑:该解决方案假定要求是“至少有两个星号”。


7
您可以使用带有正则表达式的String.matches
"^.*(?:\\*.*){2}$"

如果你想要恰好两个星号:

"^[^*]*(?:\\*[^*]*){2}$"

虽然对于这个任务来说,直接遍历字符串并计算星号可能会更简单。

2
有人能解释一下这个正则表达式吗? - ederollora
第一个可以描述为:以任意数量的字符开头,然后向前查找(两次),以查找跟随着更多字符的星号。 第二个可以描述为:以除星号之外的任何内容开头,然后向前查找(两次),以查找跟随着其他任何内容的星号。 - McKay
我认为这些代码存在漏洞,因为它们会向前查看两次,但没有任何防止向前查找两次相同内容的机制。如果你将 {2} 替换为 {45},它将继续匹配只有 1 或 2 个字符的字符串。 - McKay
请注意,这里有双反斜杠,它不是正则表达式的一部分,但是在Java中需要使用它来将反斜杠传递给正则表达式引擎以转义星号。 - McKay

3
至少有两种方法:
  • regex

    String regex = ".*\\*.*\\*.*";
    boolean valid = input.matches(regex);
    
  • loop

    int asterisks = 0;
    for (int i = 0; i < input.length(); i ++) {
        if (input.charAt(i) == '*') {
            asterisks++;
        }
    }
    

你可以从正则表达式的前面和后面删除 .* 并使用 find()。这可能会更快一些。 - Joachim Sauer

3
这里有一个不依赖正则表达式的替代方案,适用于任何字面字符串:
public static boolean containsNoneOrTwo(String haystack, String needle) {
    int index = haystack.indexOf(needle);
    return (index == -1) ||
        haystack.indexOf(needle, index+1) == haystack.lastIndexOf(needle);
}

本质上,该算法是:

containsNoneOrTwo(haystack, needle)
   = haystack contains no needle OR
        haystack's second needle is also its last

1
并且要修改它以检查恰好有两个星号,只需将第三行更改为 return (index!= -1) && - Joachim Sauer

2
boolean hasTwoAsteriks(String str) {
int i;
if((i = str.indexOf("*")) != -1) {
  if ((i = str.indexOf("*", i+1)) != -1)
    return true;
return false;
}

0

为了完整性(尽管已经提供了几个很好的答案,我最喜欢Mark和Joachim的答案),这里有两个基于String.split(regex)String.split(regex, limit)的版本:

(编辑,修复错误:)

boolean containsAtLeastTwoAsterisks = ("_" + myString + "_").split("\\*", 3).length == 3;

boolean containsExactlyTwoAsterisks = ("_" + myString + "_").split("\\*").length == 3;

我根据我们的答案写了一个小小的基准测试(我知道,基准测试并不意味着太多,但它们很有趣,而且我的可能很糟糕,我知道)。无论如何,这是一个样本运行的结果:

*********************************************************************************

Testing strings with one or less asterisk

Processor: bhups
Finished. Duration: 40 ms, errors: 0

Processor: Bozho (loop version)
Finished. Duration: 33 ms, errors: 0

Processor: Bozho (regex version)
Finished. Duration: 806 ms, errors: 0

Processor: Joachim Sauer
Finished. Duration: 24 ms, errors: 0 <-- winner

Processor: Mark Byers
Finished. Duration: 1068 ms, errors: 0

Processor: seanizer
Finished. Duration: 408 ms, errors: 0

*********************************************************************************

Testing strings with exactly two asterisks

Processor: bhups
Finished. Duration: 14 ms, errors: 0 <-- winner

Processor: Bozho (loop version)
Finished. Duration: 21 ms, errors: 0

Processor: Bozho (regex version)
Finished. Duration: 693 ms, errors: 0

Processor: Joachim Sauer
Finished. Duration: 14 ms, errors: 0 <-- winner

Processor: Mark Byers
Finished. Duration: 491 ms, errors: 0

Processor: seanizer
Finished. Duration: 340 ms, errors: 0

*********************************************************************************

Testing strings with more than two asterisks (not all processors will be included)

Skipping processor bhups

Processor: Bozho (loop version)
Finished. Duration: 63 ms, errors: 0  <-- winner

Skipping processor Bozho (regex version)

Skipping processor Joachim Sauer

Processor: Mark Byers
Finished. Duration: 1555 ms, errors: 0

Processor: seanizer
Finished. Duration: 860 ms, errors: 0

似乎非正则表达式比正则表达式快很多。我想这是你所期望的。

编辑:修正错误的获胜者。抱歉,Joachim。


你说得对,我在看到你的评论之前就自己找到了。已经修复了。 - Sean Patrick Floyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接