How do I count the number of occurrences of a char in a String?How do I count the number of occurrences of a char in a String? - Solution Checker - solutionschecker.com - Find the solution for any programming question. We as a solution checker will focus on finding the fastest possible solution for developers. Main topics like coding, learning.

I have the string

a.b.c.d

I want to count the occurrences of '.' in an idiomatic way, preferably a one-liner.

(Previously I had expressed this constraint as "without a loop", in case you're wondering why everyone's trying to answer without using a loop).

Solution 1

How about this. It doesn't use regexp underneath so should be faster than some of the other solutions and won't use a loop.

int count = line.length() - line.replace(".", "").length();

Solution 2

My 'idiomatic one-liner' for this is:

int count = StringUtils.countMatches("a.b.c.d", ".");

Why write it yourself when it's already in commons lang?

Spring Framework's oneliner for this is:

int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");

Solution 3

Summarize other answer and what I know all ways to do this using a one-liner:

   String testString = "a.b.c.d";

1) Using Apache Commons

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

2) Using Spring Framework's

int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, ".");
System.out.println("spring = " + spring);

3) Using replace

int replace = testString.length() - testString.replace(".", "").length();
System.out.println("replace = " + replace);

4) Using replaceAll (case 1)

int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);

5) Using replaceAll (case 2)

int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);

6) Using split

int split = testString.split("\\.",-1).length-1;
System.out.println("split = " + split);

7) Using Java8 (case 1)

long java8 = testString.chars().filter(ch -> ch =='.').count();
System.out.println("java8 = " + java8);

8) Using Java8 (case 2), may be better for unicode than case 1

long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count();
System.out.println("java8 (second case) = " + java8Case2);

9) Using StringTokenizer

int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);

From comment: Be carefull for the StringTokenizer, for a.b.c.d it will work but for a...b.c....d or ...a.b.c.d or a....b......c.....d... or etc. it will not work. It just will count for . between characters just once

More info in github

Perfomance test (using JMH, mode = AverageTime, score 0.010 better then 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

Solution 4

Sooner or later, something has to loop. It's far simpler for you to write the (very simple) loop than to use something like split which is much more powerful than you need.

By all means encapsulate the loop in a separate method, e.g.

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

Then you don't need have the loop in your main code - but the loop has to be there somewhere.

Solution 5

I had an idea similar to Mladen, but the opposite...

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);

Solution 6

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

ReplaceAll(".") would replace all characters.

PhiLho's solution uses ReplaceAll("[^.]",""), which does not need to be escaped, since [.] represents the character 'dot', not 'any character'.

Solution 7

My 'idiomatic one-liner' solution:

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

Have no idea why a solution that uses StringUtils is accepted.

Solution 8

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

Solution 9

A shorter example is

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

Solution 10

here is a solution without a loop:

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

well, there is a loop, but it is invisible :-)

-- Yonatan

Solution 11

I don't like the idea of allocating a new string for this purpose. And as the string already has a char array in the back where it stores it's value, String.charAt() is practically free.

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

does the trick, without additional allocations that need collection, in 1 line or less, with only J2SE.

Solution 12

Okay, inspired by Yonatan's solution, here's one which is purely recursive - the only library methods used are length() and charAt(), neither of which do any looping:

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

Whether recursion counts as looping depends on which exact definition you use, but it's probably as close as you'll get.

I don't know whether most JVMs do tail-recursion these days... if not you'll get the eponymous stack overflow for suitably long strings, of course.

Solution 13

Not sure about the efficiency of this, but it's the shortest code I could write without bringing in 3rd party libs:

public static int numberOf(String target, String content)
{
    return (content.split(target).length - 1);
}

Solution 14

Inspired by Jon Skeet, a non-loop version that wont blow your stack. Also useful starting point if you want to use the fork-join framework.

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

(Disclaimer: Not tested, not compiled, not sensible.)

Perhaps the best (single-threaded, no surrogate-pair support) way to write it:

public static int countOccurrences(String haystack, char needle) {
    int count = 0;
    for (char c : haystack.toCharArray()) {
        if (c == needle) {
           ++count;
        }
    }
    return count;
}

Solution 15

With you could also use streams to achieve this. Obviously there is an iteration behind the scenes, but you don't have to write it explicitly!

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

Solution 16

Also possible to use reduce in Java 8 to solve this problem:

int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);

Output:

3

Solution 17

The simplest way to get the answer is as follow:

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

Solution 18

Complete sample:

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

Call:

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

Solution 19

In case you're using Spring framework, you might also use "StringUtils" class. The method would be "countOccurrencesOf".

Solution 20

You can use the split() function in just one line code

int noOccurence=string.split("#",-1).length-1;

Solution 21

A much easier solution would be to just the split the string based on the character you're matching it with.

For instance,

int getOccurences(String characters, String string) { String[] words = string.split(characters); return words.length - 1; }

This will return 4 in the case of: getOccurences("o", "something about a quick brown fox");

Solution 22

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

Solution 23

While methods can hide it, there is no way to count without a loop (or recursion). You want to use a char[] for performance reasons though.

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

Using replaceAll (that is RE) does not sound like the best way to go.

Solution 24

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

Solution 25

Well, with a quite similar task I stumbled upon this Thread. I did not see any programming language restriction and since groovy runs on a java vm: Here is how I was able to solve my Problem using Groovy.

"a.b.c.".count(".")

done.

Solution 26

Using Eclipse Collections

int count = Strings.asChars("a.b.c.d").count(c -> c == '.');

If you have more than one character to count, you can use a CharBag as follows:

CharBag bag = Strings.asChars("a.b.c.d").toBag();
int count = bag.occurrencesOf('.');

Note: I am a committer for Eclipse Collections.

Solution 27

Somewhere in the code, something has to loop. The only way around this is a complete unrolling of the loop:

int numDots = 0;
if (s.charAt(0) == '.') {
    numDots++;
}

if (s.charAt(1) == '.') {
    numDots++;
}


if (s.charAt(2) == '.') {
    numDots++;
}

...etc, but then you're the one doing the loop, manually, in the source editor - instead of the computer that will run it. See the pseudocode:

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

Solution 28

Here is a slightly different style recursion solution:

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

Solution 29

Why not just split on the character and then get the length of the resulting array. array length will always be number of instances + 1. Right?

Solution 30

The following source code will give you no.of occurrences of a given string in a word entered by user :-

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

    }
}