Simple way to count character occurrences in a string

442,511

Solution 1

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

Functional style (Java 8, just for fun):

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

Solution 3

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

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

Solution 5

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
Share:
442,511
George Kastrinis
Author by

George Kastrinis

(contact: gkastrinis.info) Phd Candidate on program analysis Research on program analysis I love programming in general, and the mindset that it requires.

Updated on July 05, 2022

Comments

  • George Kastrinis
    George Kastrinis almost 2 years

    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.

  • Mark Amery
    Mark Amery about 11 years
    This works, but it's confusing and overcomplicated. Why use recursion - let alone this convoluted implementation - when iteration can be used simply and cleanly? Also, indexOffinds the leftmost index of the target string, so countChars(input.substring(0, input.indexOf(find)), find) will always be equal to zero; you could scrap the first line of your return expression and get the same result.
  • jahroy
    jahroy almost 11 years
    Regex = cleaner? Maybe shorter, but I would say regexes are generally pretty cryptic (and less clean) when compared to basic looping code.
  • user3090078
    user3090078 about 10 years
    Yahoo! I got voted up! My first post ever :-D
  • user3090078
    user3090078 about 10 years
    @Marcelo solution looks nice but fails with: "$$$$$$$$".split("\\$").length - 1 which = -1 or "$$$$$$$$".split("$").length - 1 which = 0.
  • noddy
    noddy almost 10 years
    Almost a good idea. This fails on some simple cases though. e.g. s = "$"
  • Dmitry Ginzburg
    Dmitry Ginzburg almost 10 years
    Ooh, don't you mind using enhanced for loop instead of C-style going through indices?
  • Daniel
    Daniel almost 10 years
    I don't want to use implicit iterators.
  • Dmitry Ginzburg
    Dmitry Ginzburg almost 10 years
    firstly, surely, there's no shame to use iterators, what's the problem? Secondly, iterators are not used for looping arrays, see, for example, stackoverflow.com/a/7956673/1828937.
  • Daniel
    Daniel almost 10 years
    @DmitryGinzburg: The problem is we don't have a char array here, but a String. The alternate way would be to iterate over s.toCharArray(), but this would involve a copy of the Strings internal char array.
  • Boann
    Boann over 9 years
    Doesn't work because $ is a regex metacharacter.
  • Chase
    Chase over 9 years
    This is needlessly complex, you can just use an array (256 long if only only basic characters are used, or 65535 long for the entire range java supports). do something like array[str.charAt(i)]++ instead of that if/else branch, and then on the output, just do for(int i = 0; i < length; ++i) if(array[i] != 0) System.out.println((char)i + " = " + array[i]).
  • Marcelo
    Marcelo over 9 years
    I corrected the meta character issue in the answer.
  • Kaveesh Kanwal
    Kaveesh Kanwal about 9 years
    But, what if we have to find each character's occurrence in the string?
  • RajaReddy PolamReddy
    RajaReddy PolamReddy over 8 years
    this is the best way :)
  • Hirofumi Okino
    Hirofumi Okino over 8 years
    That still doesn't work with trailing "$"s, e.g. "abdsd3$asda$asasdd$sadas$" , because empty trailing items are ignored by default. It should be int counter = s.split("\$", -1).length - 1;
  • Yeti
    Yeti almost 8 years
    "\$" should be replaced with "\\$", because the backslash already has a special meaning that is unique to the string itself, such as newlines, tabs, etc. (escape character) Therefore a double backslash is needed.
  • Sameer Kazi
    Sameer Kazi over 6 years
    waw super like !
  • oyenigun
    oyenigun over 6 years
    it doesn't work in case of last char searching ex:"356595".split("5") -> size =3 "356559".split("5") -> size = 4
  • Kalpak Gadre
    Kalpak Gadre over 6 years
    I always prefer apache commons
  • Integraty_beast
    Integraty_beast over 4 years
    can't understand clearly