Simple way to count character occurrences in a string

JavaString

Java Problem Overview


Is there a simple way (instead of traversing manually all the string, or loop for indexOf) in order to find how many times, a character appears in a string?

Say we have "abdsd3$asda$asasdd$sadas" and we want that $ appears 3 times.

Java Solutions


Solution 1 - Java

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

This is definitely the fastest way. Regexes are much much slower here, and possible harder to understand.

Solution 2 - Java

Functional style (Java 8, just for fun):

str.chars().filter(num -> num == '$').count()

Solution 3 - Java

Not optimal, but simple way to count occurrences:

String s = "...";
int counter = s.split("\\$", -1).length - 1;

Note:

  • Dollar sign is a special Regular Expression symbol, so it must be escaped with a backslash.
  • A backslash is a special symbol for escape characters such as newlines, so it must be escaped with a backslash.
  • The second argument of split prevents empty trailing strings from being removed.

Solution 4 - Java

You can use [Apache Commons][1]' StringUtils.countMatches(String string, String subStringToCount).

[1]: https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html#countMatches%28java.lang.String,%20java.lang.String%29 "Apache Commons"

Solution 5 - Java

Since you're scanning the whole string anyway you can build a full character count and do any number of lookups, all for the same big-Oh cost (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

Solution 6 - Java

A character frequency count is a common task for some applications (such as education) but not general enough to warrant inclusion with the core Java APIs. As such, you'll probably need to write your own function.

Solution 7 - Java

I believe the "one liner" that you expected to get is this:

"abdsd3$asda$asasdd$sadas".replaceAll( "[^$]*($)?", "$1" ).length();

Remember that the requirements are:

> (instead of traversing manually all the string, or loop for indexOf)

and let me add: that at the heart of this question it sounds like "any loop" is not wanted and there is no requirement for speed. I believe the subtext of this question is coolness factor.

Solution 8 - Java

you can also use a for each loop. I think it is simpler to read.

int occurrences = 0;
for(char c : yourString.toCharArray()){
   if(c == '$'){
      occurrences++;
   }
}

Solution 9 - Java

Something a bit more functional, without Regex:

public static int count(String s, char c) {
	return s.length()==0 ? 0 : (s.charAt(0)==c ? 1 : 0) + count(s.substring(1),c);
}

It's no tail recursive, for the sake of clarity.

Solution 10 - Java

Traversing the string is probably the most efficient, though using Regex to do this might yield cleaner looking code (though you can always hide your traverse code in a function).

Solution 11 - Java

Well there are a bunch of different utilities for this, e.g. Apache Commons Lang String Utils

but in the end, it has to loop over the string to count the occurrences one way or another.

Note also that the countMatches method above has the following signature so will work for substrings as well.

public static int countMatches(String str, String sub)

The source for this is (from here):

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

I was curious if they were iterating over the string or using Regex.

Solution 12 - Java

This is simple code, but of course a little bit slower.

String s = ...;
int countDollar = s.length()-s.replaceAll("\\$","").length();
int counta = s.length()-s.replaceAll("a","").length();

An even better answer is here in a duplicate question

Solution 13 - Java

You can look at sorting the string -- treat it as a char array -- and then do a modified binary search which counts occurrences? But I agree with @tofutim that traversing it is the most efficient -- O(N) versus O(N * logN) + O(logN)

Solution 14 - Java

There is another way to count the number of characters in each string. Assuming we have a String as String str = "abfdvdvdfv"

We can then count the number of times each character appears by traversing only once as

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

We can then check the output by traversing the Map as

for (Map.Entry<String, Integer> entry:map.entrySet()) 
{
    System.out.println(entry.getKey()+" count is : "+entry.getValue())

}

Solution 15 - Java

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGeorge KastrinisView Question on Stackoverflow
Solution 1 - JavaDanielView Answer on Stackoverflow
Solution 2 - JavaDmitry GinzburgView Answer on Stackoverflow
Solution 3 - JavaMarceloView Answer on Stackoverflow
Solution 4 - JavatherschView Answer on Stackoverflow
Solution 5 - JavamaericsView Answer on Stackoverflow
Solution 6 - JavamaericsView Answer on Stackoverflow
Solution 7 - Javauser3090078View Answer on Stackoverflow
Solution 8 - JavaironmaurusView Answer on Stackoverflow
Solution 9 - JavasrcarroView Answer on Stackoverflow
Solution 10 - JavatofutimView Answer on Stackoverflow
Solution 11 - JavaCaseyView Answer on Stackoverflow
Solution 12 - JavaMartin VatshelleView Answer on Stackoverflow
Solution 13 - JavaLivView Answer on Stackoverflow
Solution 14 - JavaPipoTellsView Answer on Stackoverflow
Solution 15 - JavaAnil GanivadaView Answer on Stackoverflow