关于java:如何计算String中char的出现次数?

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
   String testString ="a.b.c.d";

1)使用Apache Commons

1
2
int apache = StringUtils.countMatches(testString,".");
System.out.println("apache =" + apache);

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
int split = testString.split("\\.",-1).length-1;
System.out.println("split =" + split);

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,模式=平均时间,0.0100.351得分好):

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


迟早会有一些事情发生。对于您来说,编写(非常简单的)循环要比使用像split这样比您需要的功能强大得多的东西简单得多。

无论如何,都要用单独的方法封装循环,例如

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
String s ="a.b.c.d";
int charCount = s.replaceAll("[^.]","").length();
println(charCount);


1
2
String s ="a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.","").length();

replaceall(".")将替换所有字符。

Philho的解决方案使用replaceall("[^.]",","),它不需要转义,因为[.]表示字符"dot",而不是"any character"。


我的"惯用一行程序"解决方案:

1
int count ="a.b.c.d".length() -"a.b.c.d".replace(".","").length();

不知道为什么接受使用StringUtils的解决方案。


1
2
String s ="a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();


一个较短的例子是

1
2
String text ="a.b.c.d";
int count = text.split("\\.",-1).length-1;


这里有一个没有循环的解决方案:

1
2
3
4
5
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("a.b.c.d",'.',0));

嗯,有一个循环,但它是不可见的:—)

——Yonatan


我不喜欢为此目的分配新字符串的想法。由于字符串的后面已经有了一个char数组,所以string.charat()实际上是免费的。

1
for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))

不需要额外的分配,只需要使用J2SE,就可以在一行或更少行中完成这个技巧。


好吧,受Yonatan的解决方案的启发,这里有一个纯粹递归的库方法——使用的唯一库方法是length()charAt(),两者都不做任何循环:

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
public static int numberOf(String target, String content)
{
    return (content.split(target).length - 1);
}


使用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
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;
  }
}

呼叫:

1
2
int occurrences = CharacterCounter.countOccurrences("l","Hello World.");
System.out.println(occurrences); // 3


在使用Spring框架的情况下,也可以使用"StringUtils"类。方法将为"CountOccurrencesOf"。


得到答案的最简单方法如下:

1
2
3
4
5
public static void main(String[] args) {
    String string ="a.b.c.d";
    String []splitArray = string.split("\\.");
    System.out.println("No of . chars is :" + splitArray.length-1);
}


也可以使用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

您可以在一行代码中使用split()函数

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
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;
}

在代码的某个地方,必须循环一些东西。唯一的方法是完全展开循环:

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 == '.');

如果要计数的字符不止一个,则可以使用CharBag,如下所示:

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
 public static int countSubstring(String subStr, String str) {

    int count = 0;
    for (int i = 0; i < str.length(); i++) {
        if (str.substring(i).startsWith(subStr)) {
            count++;
        }
    }
    return count;
}

下面的递归算法呢?它也是线性时间。

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);
}

}