How do I count the number of occurrences of a char in a String?
我有绳子
1 | a.b.c.d |
我想用惯用的方法计算"."的出现次数,最好是一行。
(以前我把这个约束表示为"没有循环",以防您想知道为什么每个人都试图回答而不使用循环)。
这个怎么样?它不在下面使用regexp,因此应该比其他一些解决方案更快,并且不会使用循环。
1 | int count = line.length() - line.replace(".","").length(); |
我的"惯用一行"是:
1 | int count = StringUtils.countMatches("a.b.c.d","."); |
既然已经在通用语言中了,为什么还要自己写呢?
弹簧框架的一个内衬是:
1 | int occurance = StringUtils.countOccurrencesOf("a.b.c.d","."); |
用一句话总结其他答案以及我知道的所有方法:
1 |
1)使用Apache Commons
1 2 |
2)使用弹簧框架
1 2 | int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString,"."); System.out.println("spring =" + spring); |
3)使用替换
1 2 | int replace = testString.length() - testString.replace(".","").length(); System.out.println("replace =" + replace); |
4)使用replaceall(案例1)
1 2 | int replaceAll = testString.replaceAll("[^.]","").length(); System.out.println("replaceAll =" + replaceAll); |
5)使用替代品(案例2)
1 2 | int replaceAllCase2 = testString.length() - testString.replaceAll("\\.","").length(); System.out.println("replaceAll (second case) =" + replaceAllCase2); |
6)使用分裂
1 2 |
7)使用java8(案例1)
1 2 | long java8 = testString.chars().filter(ch -> ch =='.').count(); System.out.println("java8 =" + java8); |
8)使用java8(案例2)可能比案例1更适合Unicode。
1 2 | long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count(); System.out.println("java8 (second case) =" + java8Case2); |
9)使用StringTokenizer
1 2 | int stringTokenizer = new StringTokenizer("" +testString +"",".").countTokens()-1; System.out.println("stringTokenizer =" + stringTokenizer); |
摘自评论:小心StringTokenizer,对于A.B.C.D,它将工作,但对于A.B.C.D或A.B.C.D或A.B.C.D…等等,它不起作用。它只会算数。字符之间只需一次
GitHub中的更多信息
性能测试(使用JMH,模式=平均时间,
1 2 3 4 5 6 7 8 9 10 | 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 |
迟早会有一些事情发生。对于您来说,编写(非常简单的)循环要比使用像
无论如何,都要用单独的方法封装循环,例如
1 2 3 4 5 6 7 8 9 10 11 12 | 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; } |
然后,您不需要在主代码中包含循环——但是循环必须在某个地方。
我有一个和姆亚丁相似的想法,但恰恰相反…
1 2 3 |
1 2 |
replaceall(".")将替换所有字符。
Philho的解决方案使用replaceall("[^.]",","),它不需要转义,因为[.]表示字符"dot",而不是"any character"。
我的"惯用一行程序"解决方案:
1 | int count ="a.b.c.d".length() -"a.b.c.d".replace(".","").length(); |
不知道为什么接受使用StringUtils的解决方案。
1 2 |
一个较短的例子是
1 2 |
这里有一个没有循环的解决方案:
1 2 3 4 5 |
嗯,有一个循环,但它是不可见的:—)
——Yonatan
我不喜欢为此目的分配新字符串的想法。由于字符串的后面已经有了一个char数组,所以string.charat()实际上是免费的。
1 | for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0)) |
不需要额外的分配,只需要使用J2SE,就可以在一行或更少行中完成这个技巧。
好吧,受Yonatan的解决方案的启发,这里有一个纯粹递归的库方法——使用的唯一库方法是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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); } |
递归是否算作循环取决于您使用的确切定义,但它可能与您将得到的定义一样接近。
我不知道现在大多数JVM是否都进行尾递归…当然,如果不是这样的话,您将得到适当长字符串的同名堆栈溢出。
灵感来源于乔恩·斯基特,这是一款不会让你崩溃的非循环版本。如果您想使用fork-join框架,这也是一个有用的起点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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); } } |
(免责声明:未测试、未编译、不合理。)
最好的(单线程,不支持代理对)编写方法是:
1 2 3 4 5 6 7 8 9 | public static int countOccurrences(String haystack, char needle) { int count = 0; for (char c : haystack.toCharArray()) { if (c == needle) { ++count; } } return count; } |
不知道这是否有效,但这是我在不引入第三方libs的情况下编写的最短代码:
1 2 3 4 |
使用Java-8,您还可以使用流来实现这一点。很明显,在幕后有一个迭代,但是您不必显式地编写它!
1 2 3 4 5 6 | public static long countOccurences(String s, char c){ return s.chars().filter(ch -> ch == c).count(); } countOccurences("a.b.c.d", '.'); //3 countOccurences("hello world", 'l'); //3 |
完整样品:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
呼叫:
1 2 | int occurrences = CharacterCounter.countOccurrences("l","Hello World."); System.out.println(occurrences); // 3 |
在使用Spring框架的情况下,也可以使用"StringUtils"类。方法将为"CountOccurrencesOf"。
得到答案的最简单方法如下:
1 2 3 4 5 |
也可以使用Java 8中的Read来解决这个问题:
1 2 | int res ="abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0)); System.out.println(res); |
输出:
1 | 3 |
您可以在一行代码中使用
1 | int noOccurence=string.split("#").length-1; |
1 2 3 4 5 6 7 8 9 10 11 | 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 |
虽然方法可以隐藏它,但是没有循环(或递归)就无法计数。但出于性能原因,您需要使用char[]。
1 2 3 4 5 6 7 8 9 10 | 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)听起来不是最好的方法。
1 2 3 4 5 6 7 8 9 10 11 12 |
在代码的某个地方,必须循环一些东西。唯一的方法是完全展开循环:
1 2 3 4 5 6 7 8 9 10 11 12 13 | int numDots = 0; if (s.charAt(0) == '.') { numDots++; } if (s.charAt(1) == '.') { numDots++; } if (s.charAt(2) == '.') { numDots++; } |
…等等,但是你是在源代码编辑器中手动执行循环的人,而不是运行它的计算机。参见伪代码:
1 2 3 4 5 6 7 8 9 | 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 |
为什么不直接拆分字符,然后获取结果数组的长度呢?数组长度始终为实例数+1。对吗?
这里有一个稍微不同的风格递归解决方案:
1 2 3 4 5 6 7 8 9 10 | 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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); } } } |
1 | int count = (line.length() - line.replace("str","").length())/"str".length(); |
嗯,有一个非常相似的任务,我偶然发现了这个线索。我没有看到任何编程语言的限制,因为Groovy在Java VM上运行:下面是我如何使用groovy解决我的问题。
1 | "a.b.c.".count(".") |
完成。
使用Eclipse集合
1 | int count = CharAdapter.adapt("a.b.c.d").count(c -> c == '.'); |
如果要计数的字符不止一个,则可以使用
1 2 | CharBag bag = CharAdapter.adapt("a.b.c.d").toBag(); int count = bag.occurrencesOf('.'); |
注意:我是Eclipse集合的提交者。
你为什么要避开这个循环?我的意思是,如果不检查字符串中的每个字符,就无法计算"numberoof"点,如果调用任何函数,它将以某种方式循环。也就是说,string.replace应该执行一个循环,验证字符串是否出现,以便它可以替换每一次出现的字符串。
如果你试图减少资源使用,你不会这样做,因为你创建了一个新的字符串只是为了计算点。
现在,如果我们讨论递归的"enter code here"方法,有人说它将由于outofmemmoryexception而失败,我认为他忘记了stackoverflowexception。
所以我的方法是这样的(我知道它和其他方法一样,但是这个问题需要循环):
1 2 3 4 5 6 7 8 9 | public static int numberOf(String str,int c) { int res=0; if(str==null) return res; for(int i=0;i<str.length();i++) if(c==str.charAt(i)) res++; return res; } |
尝试此方法:
1 2 | StringTokenizer stOR = new StringTokenizer(someExpression,"||"); int orCount = stOR.countTokens()-1; |
我看到了很多技巧和使用。现在我并不反对漂亮的技巧,但我个人喜欢简单地称之为完成工作的方法,所以我已经创建了另一个答案。
请注意,如果性能有任何问题,请使用jon skeet的答案。在我看来,这一个更为一般化,因此可读性稍高(当然,对于字符串和模式来说是可重用的)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public static int countOccurances(char c, String input) { return countOccurancesOfPattern(Pattern.quote(Character.toString(c)), input); } public static int countOccurances(String s, String input) { return countOccurancesOfPattern(Pattern.quote(s), input); } public static int countOccurancesOfPattern(String pattern, String input) { Matcher m = Pattern.compile(pattern).matcher(input); int count = 0; while (m.find()) { count++; } return count; } |
1 2 3 4 5 | String[] parts = text.split("."); int occurances = parts.length - 1; " It's a great day at O.S.G. Dallas!" -- Famous Last Words |
这是一个了解Java的例子,尤其是对Java中已经可用的集合类的基本理解。如果你仔细看整篇文章,除了史蒂芬·霍金对宇宙起源的解释,达尔文的平装本《进化论》和吉恩·罗登贝里的《星际迷航》的选集外,几乎什么都没有,他们为什么要和威廉·沙特纳一起去,除了如何快速而轻松地做到这一点……
…需要我再说一遍吗?
1 2 3 4 5 6 7 8 9 10 |
下面的递归算法呢?它也是线性时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import java.lang.*; import java.util.*; class longestSubstr{ public static void main(String[] args){ String s="ABDEFGABEF"; int ans=calc(s); System.out.println("Max nonrepeating seq="+ans); } public static int calc(String s) {//s.s int n=s.length(); int max=1; if(n==1) return 1; if(n==2) { if(s.charAt(0)==s.charAt(1)) return 1; else return 2; } String s1=s; String a=s.charAt(n-1)+""; s1=s1.replace(a,""); // System.out.println(s+""+(n-2)+""+s.substring(0,n-1)); max=Math.max(calc(s.substring(0,n-1)),(calc(s1)+1)); return max; } } |
试试这个代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | package com.java.test; import java.util.HashMap; import java.util.Map; public class TestCuntstring { public static void main(String[] args) { String name ="Bissssmmayaa"; char[] ar = new char[name.length()]; for (int i = 0; i < name.length(); i++) { ar[i] = name.charAt(i); } Map<Character, String> map=new HashMap<Character, String>(); for (int i = 0; i < ar.length; i++) { int count=0; for (int j = 0; j < ar.length; j++) { if(ar[i]==ar[j]){ count++; } } map.put(ar[i], count+" no of times"); } System.out.println(map); } } |
如果要计算字符串"selenium"中相同字符的数目,或者要打印字符串"selenium"的唯一字符。
公共类计数字符串中的字符u{
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public static void main(String []args){ String s ="SELENIUM"; System.out.println(s); int counter; String g =""; for( int i=0; i<s.length(); i++ ) { if(g.indexOf(s.charAt(i)) == - 1){ g=g+s.charAt(i); } } System.out.println(g +""); for( int i=0; i<g.length(); i++ ) { System.out.print(","); System.out.print(s.charAt(i)+" :"); counter=0; for( int j=0; j<s.length(); j++ ) { if( g.charAt(i) == s.charAt(j) ) { counter=counter+1; } } System.out.print(counter); } } |
}
/*********************输出/
硒
塞勒姆
S:1,E:2,L:1,E:1,N:1,I:1,U:1
公共静态void getcharacter(字符串str){
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | int count[]= new int[256]; for(int i=0;i<str.length(); i++){ count[str.charAt(i)]++; } System.out.println("The ascii values are:"+ Arrays.toString(count)); //Now display wht character is repeated how many times for (int i = 0; i < count.length; i++) { if (count[i] > 0) System.out.println("Number of" + (char) i +":" + count[i]); } } |
}
1 | public class OccurencesInString { public static void main(String[] args) { String str ="NARENDRA AMILINENI"; HashMap occur = new HashMap(); int count =0; String key = null; for(int i=0;i<str.length()-1;i++){ key = String.valueOf(str.charAt(i)); if(occur.containsKey(key)){ count = (Integer)occur.get(key); occur.put(key,++count); }else{ occur.put(key,1); } } System.out.println(occur); } } |
我试图用switch语句来解决您的问题,但我仍然需要一个for循环来解析字符串。如果我能改进代码,请随时发表评论
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | public class CharacterCount { public static void main(String args[]) { String message="hello how are you"; char[] array=message.toCharArray(); int a=0; int b=0; int c=0; int d=0; int e=0; int f=0; int g=0; int h=0; int i=0; int space=0; int j=0; int k=0; int l=0; int m=0; int n=0; int o=0; int p=0; int q=0; int r=0; int s=0; int t=0; int u=0; int v=0; int w=0; int x=0; int y=0; int z=0; for(char element:array) { switch(element) { case 'a': a++; break; case 'b': b++; break; case 'c':c++; break; case 'd':d++; break; case 'e':e++; break; case 'f':f++; break; case 'g':g++; break; case 'h': h++; break; case 'i':i++; break; case 'j':j++; break; case 'k':k++; break; case 'l':l++; break; case 'm':m++; break; case 'n':m++; break; case 'o':o++; break; case 'p':p++; break; case 'q':q++; break; case 'r':r++; break; case 's':s++; break; case 't':t++; break; case 'u':u++; break; case 'v':v++; break; case 'w':w++; break; case 'x':x++; break; case 'y':y++; break; case 'z':z++; break; case ' ':space++; break; default :break; } } System.out.println("A"+a+" B"+ b +" C"+c+" D"+d+" E"+e+" F"+f+" G"+g+" H"+h); System.out.println("I"+i+" J"+j+" K"+k+" L"+l+" M"+m+" N"+n+" O"+o+" P"+p); System.out.println("Q"+q+" R"+r+" S"+s+" T"+t+" U"+u+" V"+v+" W"+w+" X"+x+" Y"+y+" Z"+z); System.out.println("SPACE"+space); } |
}