字符串中子字符串的出现

时间:2009-04-20 10:47:52

标签: java string

为什么以下算法不会停止? (str是我正在搜索的字符串,findStr是我想要查找的字符串)

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while (lastIndex != -1) {
    lastIndex = str.indexOf(findStr,lastIndex);

    if( lastIndex != -1)
        count++;

    lastIndex += findStr.length();
}

System.out.println(count);

26 个答案:

答案 0 :(得分:175)

如何使用Apache Commons Lang的StringUtils.countMatches

String str = "helloslkhellodjladfjhello";
String findStr = "hello";

System.out.println(StringUtils.countMatches(str, findStr));

输出:

3

答案 1 :(得分:111)

您的lastIndex += findStr.length();被放置在括号外,导致无限循环(当未发现任何事件时,最后一个索引始终为findStr.length())。

这是固定版本:

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while (lastIndex != -1) {

    lastIndex = str.indexOf(findStr, lastIndex);

    if (lastIndex != -1) {
        count++;
        lastIndex += findStr.length();
    }
}
System.out.println(count);

答案 2 :(得分:84)

较短的版本。 ;)

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
System.out.println(str.split(findStr, -1).length-1);

答案 3 :(得分:81)

最后一行是造成问题。 lastIndex永远不会是-1,所以会有一个无限循环。这可以通过将最后一行代码移动到if块中来解决。

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while(lastIndex != -1){

    lastIndex = str.indexOf(findStr,lastIndex);

    if(lastIndex != -1){
        count ++;
        lastIndex += findStr.length();
    }
}
System.out.println(count);

答案 4 :(得分:78)

你真的必须自己处理匹配吗?特别是如果你需要的只是出现次数,正则表达式更整洁:

String str = "helloslkhellodjladfjhello";
Pattern p = Pattern.compile("hello");
Matcher m = p.matcher(str);
int count = 0;
while (m.find()){
    count +=1;
}
System.out.println(count);     

答案 5 :(得分:9)

在这里,它包含在一个漂亮且可重复使用的方法中:

public static int count(String text, String find) {
        int index = 0, count = 0, length = find.length();
        while( (index = text.indexOf(find, index)) != -1 ) {                
                index += length; count++;
        }
        return count;
}

答案 6 :(得分:8)

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while((lastIndex = str.indexOf(findStr, lastIndex)) != -1) {
     count++;
     lastIndex += findStr.length() - 1;
}
System.out.println(count);

在循环计数结束时为3;希望它有所帮助

答案 7 :(得分:6)

public int countOfOccurrences(String str, String subStr) {
  return (str.length() - str.replaceAll(Pattern.quote(subStr), "").length()) / subStr.length();
}

答案 8 :(得分:6)

我很惊讶没有人提到这个班轮。它简单,简洁,性能略优于str.split(target, -1).length-1

public static int count(String str, String target) {
    return (str.length() - str.replace(target, "").length()) / target.length();
}

答案 9 :(得分:5)

许多给定的答案在以下一个或多个方面失败:

  • 任意长度的图案
  • 重叠匹配(例如“23232”中的“232”或“aaa”中的“aa”)
  • 正则表达式元字符

这是我写的:

static int countMatches(Pattern pattern, String string)
{
    Matcher matcher = pattern.matcher(string);

    int count = 0;
    int pos = 0;
    while (matcher.find(pos))
    {
        count++;
        pos = matcher.start() + 1;
    }

    return count;
}

示例电话:

Pattern pattern = Pattern.compile("232");
int count = countMatches(pattern, "23232"); // Returns 2

如果您想要非正则表达式搜索,只需使用LITERAL标志正确编译您的模式:

Pattern pattern = Pattern.compile("1+1", Pattern.LITERAL);
int count = countMatches(pattern, "1+1+1"); // Returns 2

答案 10 :(得分:3)

public int indexOf(int ch,
                   int fromIndex)

返回指定字符第一次出现的字符串中的索引,从指定索引处开始搜索。

因此,您的lastindex值始终为0,并且始终在字符串中找到 hello

答案 11 :(得分:3)

每当您查找下一次出现时,都会增加lastIndex

否则它总是找到第一个子串(位置0)。

答案 12 :(得分:2)

给出的答案是正确的,对于计算行返回等事情是不利的,而且过于冗长。后来的答案更好,但只需用

即可实现
str.split(findStr).length

使用问题中的示例不会丢弃尾随匹配。

答案 13 :(得分:2)

您可以使用内置库函数发生次数:

import org.springframework.util.StringUtils;
StringUtils.countOccurrencesOf(result, "R-")

答案 14 :(得分:1)

以下方法显示整个字符串中的子字符串重复次数。希望充分利用你: -

    String searchPattern="aaa"; // search string
    String str="aaaaaababaaaaaa"; // whole string
    int searchLength = searchPattern.length(); 
    int totalLength = str.length(); 
    int k = 0;
    for (int i = 0; i < totalLength - searchLength + 1; i++) {
        String subStr = str.substring(i, searchLength + i);
        if (subStr.equals(searchPattern)) {
           k++;
        }

    }

答案 15 :(得分:1)

正如@Mr_and_Mrs_D建议:

String haystack = "hellolovelyworld";
String needle = "lo";
return haystack.split(Pattern.quote(needle), -1).length - 1;

答案 16 :(得分:1)

试试这个。它用-替换所有匹配。

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int numberOfMatches = 0;
while (str.contains(findStr)){
    str = str.replaceFirst(findStr, "-");
    numberOfMatches++;
}

如果你不想破坏你的str,你可以创建一个具有相同内容的新字符串:

String str = "helloslkhellodjladfjhello";
String strDestroy = str;
String findStr = "hello";
int numberOfMatches = 0;
while (strDestroy.contains(findStr)){
    strDestroy = strDestroy.replaceFirst(findStr, "-");
    numberOfMatches++;
}

执行此块后,这些将是您的值:

str = "helloslkhellodjladfjhello"
strDestroy = "-slk-djladfj-"
findStr = "hello"
numberOfMatches = 3

答案 17 :(得分:1)

根据现有的答案,我想在没有if的情况下添加“更短”的版本:

String str = "helloslkhellodjladfjhello";
String findStr = "hello";

int count = 0, lastIndex = 0;
while((lastIndex = str.indexOf(findStr, lastIndex)) != -1) {
    lastIndex += findStr.length() - 1;
    count++;
}

System.out.println(count); // output: 3

答案 18 :(得分:1)

尝试将lastIndex+=findStr.length()添加到循环的末尾,否则您将进入无限循环,因为一旦找到子字符串,您就会尝试从同一个最后位置一次又一次地找到它。

答案 19 :(得分:0)

? 再简单一点的回答

    public int countOccurrences(String str, String sub) {
        if (str == null || str.length() == 0 || sub == null || sub.length() == 0) return 0;
        int count = 0;
        int i = 0;
        while ((i = str.indexOf(sub, i)) != -1) {
            count++;
            i += sub.length();
        }
        return count;
    }

答案 20 :(得分:0)

此解决方案可打印整个字符串中给定子字符串出现的总数,还包括确实存在重叠匹配的情况。

class SubstringMatch{
 public static void main(String []args){
    //String str = "aaaaabaabdcaa";
    //String sub = "aa";
    //String str = "caaab";
    //String sub = "aa";
    String str="abababababaabb";
    String sub = "bab";

    int n = str.length();
    int m = sub.length();

    // index=-1 in case of no match, otherwise >=0(first match position)
    int index=str.indexOf(sub), i=index+1, count=(index>=0)?1:0;
    System.out.println(i+" "+index+" "+count);

    // i will traverse up to only (m-n) position
    while(index!=-1 && i<=(n-m)){   
        index=str.substring(i, n).indexOf(sub);
        count=(index>=0)?count+1:count;
        i=i+index+1;  
        System.out.println(i+" "+index);
    }
    System.out.println("count: "+count);
 }

}

答案 21 :(得分:0)

我刚才在面试中被问到这个问题,我完全空白。 (像往常一样,我告诉自己,面试结束的那一刻就无法找到解决方案)我在电话结束后 5 分钟做到了 :(

    int subCounter=0;
    int count =0;
    for(int i=0; i<str.length(); i++) {
        if((subCounter==0 && "a".equals(str.substring(i,i+1))) 
                || (subCounter==1 && "b".equals(str.substring(i,i+1)))
                || (subCounter==2 && "c".equals(str.substring(i,i+1)))) {
            ++subCounter;
        }
        if(subCounter==3) {
            count = count+1;
            subCounter=0;
        }
    }
    System.out.println(count);

答案 22 :(得分:0)

public static int getCountSubString(String str , String sub){
int n = 0, m = 0, counter = 0, counterSub = 0;
while(n < str.length()){
  counter = 0;
  m = 0;
  while(m < sub.length() && str.charAt(n) == sub.charAt(m)){
    counter++;
    m++; n++;
  }
  if (counter == sub.length()){
    counterSub++;
    continue;
  }
  else if(counter > 0){
    continue;
  }
  n++;
}

return  counterSub;

}

答案 23 :(得分:0)

如果你需要原始字符串中每个子字符串的索引,你可以像indexOf那样做一些事情:

 private static List<Integer> getAllIndexesOfSubstringInString(String fullString, String substring) {
    int pointIndex = 0;
    List<Integer> allOccurences = new ArrayList<Integer>();
    while(fullPdfText.indexOf(substring,pointIndex) >= 0){
       allOccurences.add(fullPdfText.indexOf(substring, pointIndex));
       pointIndex = fullPdfText.indexOf(substring, pointIndex) + substring.length();
    }
    return allOccurences;
}

答案 24 :(得分:0)

这是另一种不使用regexp / patterns / matchers甚至不使用StringUtils的解决方案。

String str = "helloslkhellodjladfjhelloarunkumarhelloasdhelloaruhelloasrhello";
        String findStr = "hello";
        int count =0;
        int findStrLength = findStr.length();
        for(int i=0;i<str.length();i++){
            if(findStr.startsWith(Character.toString(str.charAt(i)))){
                if(str.substring(i).length() >= findStrLength){
                    if(str.substring(i, i+findStrLength).equals(findStr)){
                        count++;
                    }
                }
            }
        }
        System.out.println(count);

答案 25 :(得分:0)

以下是用于计算用户输入的字符串中令牌发生次数的高级版本:

public class StringIndexOf {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        System.out.println("Enter a sentence please: \n");
        String string = scanner.nextLine();

        int atIndex = 0;
        int count = 0;

        while (atIndex != -1)
        {
            atIndex = string.indexOf("hello", atIndex);

            if(atIndex != -1)
            {
                count++;
                atIndex += 5;
            }
        }

        System.out.println(count);
    }

}