计算字符串中字符出现次数的简单方法

是否有一种简单的方法(而不是手动遍历所有字符串,或者循环索引)来查找一个字符在字符串中出现的次数?

假设我们有“ abdsd3 $asda $asasdd $sadas”,我们希望 $出现3次。

458054 次浏览

遍历字符串可能是最有效的,尽管使用正则表达式这样做可能会产生更清晰的代码(尽管您总是可以在函数中隐藏您的遍历代码)。

public int countChar(String str, char c)
{
int count = 0;


for(int i=0; i < str.length(); i++)
{    if(str.charAt(i) == c)
count++;
}


return count;
}

这绝对是最快的方法。正则表达式在这里要慢得多,而且可能更难理解。

字符频率计数对于某些应用程序(如教育)来说是一项常见的任务,但是还不足以保证将其包含在核心 JavaAPI 中。因此,您可能需要编写自己的函数。

这里有很多不同的实用程序,比如 Apache Commons Lang 字符串实用程序

但最终,它必须循环遍历字符串,以某种方式计算出现的次数。

还要注意,上面的 countMatches方法具有以下签名,因此也适用于子字符串。

public static int countMatches(String str, String sub)

这个问题的来源是(来自 给你) :

public static int countMatches(String str, String sub) {
if (isEmpty(str) || isEmpty(sub)) {
return 0;
}
int count = 0;
int idx = 0;
while ((idx = str.indexOf(sub, idx)) != -1) {
count++;
idx += sub.length();
}
return count;
}

我很好奇他们是在字符串上迭代还是在使用正则表达式。

您可以考虑对字符串进行排序——将其视为一个字符数组——然后执行修改后的二进制搜索来计算出现次数?但是我同意@tofutim 的观点,即遍历它是最有效的—— O (N)对 O (N * logN) + O (logN)

不是最佳方法,但是计算事件的简单方法:

String s = "...";
int counter = s.split("\\$", -1).length - 1;

注:

  • 美元符号是一个特殊的正则表达式符号,因此必须用反斜杠转义。
  • 反斜杠是转义字符(如换行符)的特殊符号,因此必须使用反斜杠进行转义。
  • 拆分的第二个参数防止删除空的尾随字符串。
 public static int countChars(String input,char find){
if(input.indexOf(find) != -1){
return  countChars(input.substring(0, input.indexOf(find)), find)+
countChars(input.substring(input.indexOf(find)+1),find) + 1;
}
else {
return 0;
}


}

因为你无论如何都要扫描整个字符串,所以你可以构建一个完整的字符计数并进行任意数量的查找,所有的代价都是一样的-Oh 成本(n) :

public static Map<Character,Integer> getCharFreq(String s) {
Map<Character,Integer> charFreq = new HashMap<Character,Integer>();
if (s != null) {
for (Character c : s.toCharArray()) {
Integer count = charFreq.get(c);
int newCount = (count==null ? 1 : count+1);
charFreq.put(c, newCount);
}
}
return charFreq;
}


// ...
String s = "abdsd3$asda$asasdd$sadas";
Map counts = getCharFreq(s);
counts.get('$'); // => 3
counts.get('a'); // => 7
counts.get('s'); // => 6

这是一段简单的代码,但是当然要慢一些。

String s = ...;
int countDollar = s.length()-s.replaceAll("\\$","").length();
int counta = s.length()-s.replaceAll("a","").length();

一个更好的答案在 重复的问题

我相信你期望得到的“一句话”是这样的:

"abdsd3$asda$asasdd$sadas".replaceAll( "[^$]*($)?", "$1" ).length();

请记住,这些要求是:

(而不是手动遍历所有字符串循环索引)

让我补充一下: 在这个问题的核心,听起来像“任何循环”是不需要的,没有速度的要求。我相信这个问题的潜台词是 冷却系数

您也可以使用 for each 循环。我认为它更容易阅读。

int occurrences = 0;
for(char c : yourString.toCharArray()){
if(c == '$'){
occurrences++;
}
}

一些更实用的东西,没有正则表达式:

public static int count(String s, char c) {
return s.length()==0 ? 0 : (s.charAt(0)==c ? 1 : 0) + count(s.substring(1),c);
}

为了清晰起见,这不是尾部递归。

函数式样(Java8,纯粹为了好玩) :

str.chars().filter(num -> num == '$').count()

可以使用 Apache CommonsStringUtils.countMatches(String string, String subStringToCount)

还有另一种方法来计算每个字符串中的字符数。 假设我们有一个 String 作为 String str = "abfdvdvdfv"

然后,我们可以通过仅遍历一次来计算每个字符出现的次数

for (int i = 0; i < str.length(); i++)
{
if(null==map.get(str.charAt(i)+""))
{
map.put(str.charAt(i)+"", new Integer(1));
}
else
{
Integer count = map.get(str.charAt(i)+"");
map.put(str.charAt(i)+"", count+1);
}
}

然后,我们可以通过将 Map 遍历为

for (Map.Entry<String, Integer> entry:map.entrySet())
{
System.out.println(entry.getKey()+" count is : "+entry.getValue())


}