是否有一种简单的方法(而不是手动遍历所有字符串,或者循环索引)来查找一个字符在字符串中出现的次数?
假设我们有“ abdsd3 $asda $asasdd $sadas”,我们希望 $出现3次。
遍历字符串可能是最有效的,尽管使用正则表达式这样做可能会产生更清晰的代码(尽管您总是可以在函数中隐藏您的遍历代码)。
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方法具有以下签名,因此也适用于子字符串。
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 Commons’StringUtils.countMatches(String string, String subStringToCount)。
StringUtils.countMatches(String string, String subStringToCount)
还有另一种方法来计算每个字符串中的字符数。 假设我们有一个 String 作为 String str = "abfdvdvdfv"
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()) }