Java:如何计算string中字符的出现次数?
我有string
abcd
我想统计一下“。”的出现次数。 以惯用的方式,最好是单线。
(以前我曾经把这个约束expression为“没有循环”,如果你想知道为什么每个人都试图回答而不使用循环)。
我的“惯用单行”是这样的:
int count = StringUtils.countMatches("abcd", ".");
为什么当它已经在commons lang ?
Spring Framework的oneliner是这样的:
int occurance = StringUtils.countOccurrencesOf("abcd", ".");
这个怎么样。 它不使用下面的正则expression式,所以应该比其他一些解决scheme更快,并且不会使用循环。
int count = line.length() - line.replace(".", "").length();
迟早会有东西不得不循环。 编写(非常简单的)循环要比使用比你需要的更强大的split
更简单。
通过一切手段封装循环在一个单独的方法,例如
public static int countOccurrences(String haystack, char needle) { int count = 0; for (int i=0; i < haystack.length(); i++) { if (haystack.charAt(i) == needle) { count++; } } return count; }
那么你不需要在你的主代码中有循环 – 但循环必须在那里。
总结其他的答案和我所知道的所有方法来使用一行:
String testString = "abcd";
1)使用Apache Commons
int apache = StringUtils.countMatches(testString, "."); System.out.println("apache = " + apache);
2)使用Spring框架的
int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, "."); System.out.println("spring = " + spring);
3)使用replace
int replace = testString.length() - testString.replace(".", "").length(); System.out.println("replace = " + replace);
4)使用replaceAll (情况1)
int replaceAll = testString.replaceAll("[^.]", "").length(); System.out.println("replaceAll = " + replaceAll);
5)使用replaceAll (情况2)
int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length(); System.out.println("replaceAll (second case) = " + replaceAllCase2);
6)使用分割
int split = testString.split("\\.",-1).length-1; System.out.println("split = " + split);
7)使用Java8 (情况1)
long java8 = testString.chars().filter(ch -> ch =='.').count(); System.out.println("java8 = " + java8);
8)使用Java8 (情况2),可能比情况1更好的Unicode
long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count(); System.out.println("java8 (second case) = " + java8Case2);
9)使用StringTokenizer
int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1; System.out.println("stringTokenizer = " + stringTokenizer);
从评论 :要小心StringTokenizer,为abcd它将工作,但对于… BC … D或… ABCD或A …. B … C ….. D …等等,它不会工作。 它只是计数。 人物之间只有一次
更多信息在github
性能testing (使用JMH ,mode = AverageTime,得分0.010
优于0.351
):
Benchmark Mode Cnt Score Error Units 1. countMatches avgt 5 0.010 ± 0.001 us/op 2. countOccurrencesOf avgt 5 0.010 ± 0.001 us/op 3. stringTokenizer avgt 5 0.028 ± 0.002 us/op 4. java8_1 avgt 5 0.077 ± 0.005 us/op 5. java8_2 avgt 5 0.078 ± 0.003 us/op 6. split avgt 5 0.137 ± 0.009 us/op 7. replaceAll_2 avgt 5 0.302 ± 0.047 us/op 8. replace avgt 5 0.303 ± 0.034 us/op 9. replaceAll_1 avgt 5 0.351 ± 0.045 us/op
我有一个类似Mladen的想法,但是相反…
String s = "abcd"; int charCount = s.replaceAll("[^.]", "").length(); println(charCount);
String s = "abcd"; int charCount = s.length() - s.replaceAll("\\.", "").length();
ReplaceAll(“。”)将replace所有字符。
PhiLho的解决scheme使用了ReplaceAll(“[^。]”,“”),因为[。]代表字符“点”而不是“任何字符”,所以不需要转义。
我的“惯用一行”解决scheme:
int count = "abcd".length() - "abcd".replace(".", "").length();
不知道为什么使用StringUtils的解决scheme被接受。
String s = "abcd"; long result = s.chars().filter(ch -> ch == '.').count();
一个简短的例子是
String text = "abcd"; int count = text.split("\\.",-1).length-1;
这里是一个没有循环的解决scheme:
public static int countOccurrences(String haystack, char needle, int i){ return ((i=haystack.indexOf(needle, i)) == -1)?0:1+countOccurrences(haystack, needle, i+1);} System.out.println("num of dots is "+countOccurrences("abcd",'.',0));
好吧,有一个循环,但它是隐形的 🙂
– Yonatan
我不喜欢为此分配一个新string的想法。 而且由于string已经在后面存储了一个char数组,它的值是String.charAt()几乎是空闲的。
for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))
没有额外的需要收集的分配,在1行或更less,只有J2SE。
好吧,从Yonatan的解决scheme中得到灵感,这里是一个纯粹的recursion – 唯一使用的库方法是length()
和charAt()
,它们都没有任何循环:
public static int countOccurrences(String haystack, char needle) { return countOccurrences(haystack, needle, 0); } private static int countOccurrences(String haystack, char needle, int index) { if (index >= haystack.length()) { return 0; } int contribution = haystack.charAt(index) == needle ? 1 : 0; return contribution + countOccurrences(haystack, needle, index+1); }
recursion计数是否循环取决于您使用的确切定义,但可能与您所得到的相近。
我不知道现在大多数JVM是否执行尾recursion(tail-recursion)……当然,如果不是的话,你会得到同名的堆栈溢出。
灵感来自Jon Skeet,一个非循环版本,不会吹你的堆栈。 如果你想使用fork-join框架也是有用的起点。
public static int countOccurrences(CharSequeunce haystack, char needle) { return countOccurrences(haystack, needle, 0, haystack.length); } // Alternatively String.substring/subsequence use to be relatively efficient // on most Java library implementations, but isn't any more [2013]. private static int countOccurrences( CharSequence haystack, char needle, int start, int end ) { if (start == end) { return 0; } else if (start+1 == end) { return haystack.charAt(start) == needle ? 1 : 0; } else { int mid = (end+start)>>>1; // Watch for integer overflow... return countOccurrences(haystack, needle, start, mid) + countOccurrences(haystack, needle, mid, end); } }
(免责声明:未经testing,未编译,不明智。)
也许最好的(单线程,没有代理对支持)的方式来写它:
public static int countOccurrences(String haystack, char needle) { int count = 0; for (char c : haystack.toCharArray()) { if (c == needle) { ++count; } } return count; }
不知道这个的效率,但它是我可以写入的最短的代码,而无需引入第三方库:
public static int numberOf(String target, String content) { return (content.split(target).length - 1); }
完整的样本:
public class CharacterCounter { public static int countOccurrences(String find, String string) { int count = 0; int indexOf = 0; while (indexOf > -1) { indexOf = string.indexOf(find, indexOf + 1); if (indexOf > -1) count++; } return count; } }
呼叫:
int occurrences = CharacterCounter.countOccurrences("l", "Hello World."); System.out.println(occurrences); // 3
用java-8你也可以使用stream来实现这一点。 显然在幕后有一个迭代,但是你不需要明确地写出它!
public static long countOccurences(String s, char c){ return s.chars().filter(ch -> ch == c).count(); } countOccurences("abcd", '.'); //3 countOccurences("hello world", 'l'); //3
如果你使用Spring框架,你也可以使用“StringUtils”类。 该方法将是“countOccurrencesOf”。
import java.util.Scanner; class apples { public static void main(String args[]) { Scanner bucky = new Scanner(System.in); String hello = bucky.nextLine(); int charCount = hello.length() - hello.replaceAll("e", "").length(); System.out.println(charCount); } }// COUNTS NUMBER OF "e" CHAR´s within any string input
你可以在一行代码中使用split()
函数
int noOccurence=string.split("#").length-1;
虽然方法可以隐藏它,但没有一个循环(或recursion)没有办法计数。 不过,出于性能方面的考虑,你想使用char []。
public static int count( final String s, final char c ) { final char[] chars = s.toCharArray(); int count = 0; for(int i=0; i<chars.length; i++) { if (chars[i] == c) { count++; } } return count; }
使用replaceAll(即RE)听起来不是最好的方式。
public static int countOccurrences(String container, String content){ int lastIndex, currIndex = 0, occurrences = 0; while(true) { lastIndex = container.indexOf(content, currIndex); if(lastIndex == -1) { break; } currIndex = lastIndex + content.length(); occurrences++; } return occurrences; }
代码中的某处必须循环。 解决这个问题的唯一方法是完整地展开循环:
int numDots = 0; if (s.charAt(0) == '.') { numDots++; } if (s.charAt(1) == '.') { numDots++; } if (s.charAt(2) == '.') { numDots++; }
…等,但是你是在源代码编辑器中手动执行循环的人,而不是运行它的计算机。 看伪代码:
create a project position = 0 while (not end of string) { write check for character at position "position" (see above) } write code to output variable "numDots" compile program hand in homework do not think of the loop that your "if"s may have been optimized and compiled to
这是一个稍微不同的样式recursion解决scheme:
public static int countOccurrences(String haystack, char needle) { return countOccurrences(haystack, needle, 0); } private static int countOccurrences(String haystack, char needle, int accumulator) { if (haystack.length() == 0) return accumulator; return countOccurrences(haystack.substring(1), needle, haystack.charAt(0) == needle ? accumulator + 1 : accumulator); }
为什么不分割字符,然后得到结果数组的长度。 数组的长度将永远是实例的数量+ 1。
下面的源代码会给你一个用户input的字中给定string的出现次数: –
import java.util.Scanner; public class CountingOccurences { public static void main(String[] args) { Scanner inp= new Scanner(System.in); String str; char ch; int count=0; System.out.println("Enter the string:"); str=inp.nextLine(); while(str.length()>0) { ch=str.charAt(0); int i=0; while(str.charAt(i)==ch) { count =count+i; i++; } str.substring(count); System.out.println(ch); System.out.println(count); } } }
int count = (line.length() - line.replace("str", "").length())/"str".length();
得到答案的最简单方法如下:
public static void main(String[] args) { String string = "abcd"; String []splitArray = string.split("\\."); System.out.println("No of . chars is : " + splitArray.length-1); }
在Java 8中也可以使用reduce来解决这个问题:
int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0)); System.out.println(res);
输出:
3
使用Eclipse集合
int count = CharAdapter.adapt("abcd").count(c -> c == '.');
如果你有多个字符来计算,你可以使用一个CharBag
,如下所示:
CharBag bag = CharAdapter.adapt("abcd").toBag(); int count = bag.occurrencesOf('.');
注意:我是Eclipse集合的提交者。
试试这个方法:
StringTokenizer stOR = new StringTokenizer(someExpression, "||"); int orCount = stOR.countTokens()-1;