How do I count the number of occurrences of a char in a String?
Asked Answered
P

48

626

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

Pilot answered 9/11, 2008 at 14:7 Comment(7)
Homework? Because otherwise I don't see the requirement to avoid the loop.Pulley
Not averse to a loop so much as looking for an idiomatic one-liner.Pilot
Loops were made for a problem like this, write the loop in a common Utility class then call your freshly minted one liner.Toomin
Similar question for strings: #768259Laurielaurier
Just to point out--I appreciate finding the one-liners, it's fun and (as a true advantage) often easy to remember, but I'd like to point out that a separate method and a loop is better in just about every way--readability and even performance. Most of the "Elegant" solutions below are not going to perform very well because they involve reforming strings/copying memory, whereas a loop that just scanned the string and counted occurrences would be fast and simple. Not that performance should generally be a factor, but don't look at the one-line over a loop and assume it will perform better.Pelting
Possible duplicate of Find occurrences of characters in a Java StringTransmit
@Transmit In the future, please choose the higher upvoted questions/answers as the duplicate target.Amasa
D
784

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", ".");
Danielladanielle answered 29/11, 2009 at 22:23 Comment(7)
Guava equivalent: int count = CharMatcher.is('.').countIn("a.b.c.d"); ...As answered by dogbane in a duplicate question.Pirnot
Although i will not downvote this, it is (a) requiring 3rd party libs and (b) expensive.Enchanter
This only work with spring frame work have to import.Merissa
if someone needs it: grepcode.com/file/repo1.maven.org/maven2/commons-lang/…Sheritasherj
What's been expensive, at every company at which I've worked, is having lots of poorly-written and poorly-maintained "*Utils" classes. Part of your job is to know what's available in Apache Commons.Mesenchyme
For Maven/Gradle: mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.0Blodgett
I got a core java solution, check this : #3764470Goosestep
J
1127

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();
Jessejessee answered 18/1, 2012 at 13:17 Comment(17)
Easiest way. Clever one. And it works on Android, where there is no StringUtils classStansberry
This is the best answer. The reason it is the best is because you don't have to import another library.Coenocyte
It is not necessarily faster than other solutions like StringUtils.countMatches because it has to allocate some memory for the returned String. Still a nice solution when performance is not critical.Patrimony
Very practical but ugly as hell. I don't recommend it as it leads to confusing code.Pennant
Ugly code can be minimized by making it a method in your own "StringUtils" class. Then the ugly code is in exactly one spot, and everywhere else is nicely readable.Guttle
This has to go through the string three times; first it has to calculate the length, then it has to replace the chars to be counted (which also involves creating a new String), then it has to calculate the length again. I wonder what's so bad about a loop (obviously that's not a question for Andreas but for the OP)Brainbrainard
Just want to add one more thing for newbies. If someone is having longer string than ".", in that case divide the count with the length of the string to get the correct count of that sub-string.Devour
Doesn't String.replace(String, String) use regular expressions? Isn't . a wildcard in a regular expression? So, why wouldn't the replace create an empty string?Filterable
No, String.replace doesn't use regexp. docs.oracle.com/javase/8/docs/api/java/lang/…Jessejessee
The loop method is much faster than this. Especially when wanting to count a char instead of a String (since there is no String.replace(char, char) method). On a 15 character string, I get a difference of 6049 ns vs 26,739 ns (averaged over 100runs). Raw numbers are huge difference, but percetage wise...it adds up. Avoid the memory allocations - use a loop!Fi
String.replace(CharSequnce, CharSequence) does use regexp (look at this OpenJDK source code: goo.gl/O9dQzg) For 1 character to 1 character replaces, use String.replace(char, char) for better performance. It simply iterates over the String's characters: goo.gl/2FbcWPPhaih
Another interesting variation of this can count the occurrences of an entire string or a character: int count = (sourceString.length() - sourceString.replace(searchString, "").length())/searcString.length();Feliks
@Brainbrainard that's wrong, Java's String is not null-terminated and doesn't have to loop through the characters to determine its length. Instead it uses an array of characters internally. Array.length is O(1).Putrescible
I did not say Java strings were NUL terminated and I did not say a loop was needed to calculate length. In any case the actual implementation of a String is implementation dependent.Brainbrainard
Shouldn't this be: int count = (line.length() - line.replace(".", "").length()) / ".".length(); assuming you would want to parameterize the string "."?Tendency
Well, this answer is so embarrassing easy, not in a thousand years I would have thought of that...Primer
This is very wrong, you're allocating memory to perform counting in a linear scan.Headman
D
784

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", ".");
Danielladanielle answered 29/11, 2009 at 22:23 Comment(7)
Guava equivalent: int count = CharMatcher.is('.').countIn("a.b.c.d"); ...As answered by dogbane in a duplicate question.Pirnot
Although i will not downvote this, it is (a) requiring 3rd party libs and (b) expensive.Enchanter
This only work with spring frame work have to import.Merissa
if someone needs it: grepcode.com/file/repo1.maven.org/maven2/commons-lang/…Sheritasherj
What's been expensive, at every company at which I've worked, is having lots of poorly-written and poorly-maintained "*Utils" classes. Part of your job is to know what's available in Apache Commons.Mesenchyme
For Maven/Gradle: mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.0Blodgett
I got a core java solution, check this : #3764470Goosestep
B
335

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
Brahmaputra answered 6/2, 2016 at 15:40 Comment(3)
The printed strings do not match the ones above, and the order is fastest first which makes lookup tricky at least. Nice answer otherways!Biographer
case 2, generalized for codepoints that need more than one UTF-16 code unit: "1🚲2🚲3 has 2".codePoints().filter((c) -> c == "🚲".codePointAt(0)).count()Rosaline
Apache Commons's StringUtils.countMatches loops over indices and uses charAt; Spring Framework's StringUtils.countOccurencesOf uses indexOf repeatedly. (OpenJDK's String.indexOf basically uses charAt in a loop.)Pernell
V
184

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.

Vacationist answered 9/11, 2008 at 14:38 Comment(11)
for (int i=0,l=haystack.length(); i < l; i++) be kind to your stackInfantryman
(I'm not even sure where the "stack" bit of the comment comes from. It's not like this answer is my recursive one, which is indeed nasty to the stack.)Vacationist
not only that but this is possibly an anti optimization without taking a look at what the jit does. If you did the above on an array for loop for example you might make things worse.Trass
I think @Infantryman has concerns about length() being called very often, which might make a performance difference when dealing with large strings. Chris' suggestion reduces access to length() to a single call.Laddie
@sulai: Chris's concern is baseless, IMO, in the face of a trivial JIT optimization. Is there any reason that comment drew your attention at the moment, over three years later? Just interested.Vacationist
Probably @Laddie just came across the question as I did (while wondering if Java had a built-in method for this) and didn't notice the dates. However, I'm curious how moving the length() call outside of the loop could make performance worse, as mentioned by @Trass a few comments up.Sidras
Something has to loop, I agree, but this is more terse: for (int i = 0; (i = haystack.indexOf(needle, i)) >= 0; i++) { count++; } Can be criticized for being a bit cryptic, of course.Invitatory
@njlarsson: Then you've got a loop within the loop, just not as obviously. And yes, I'd say that's considerably harder to read.Vacationist
@JonSkeet I suppose you are right. I was thinking “dramatically reduces the number of function calls if needle is rare”, but I guess charAt will be inlined if this is critical code.Invitatory
(Sorry for commenting on an old post) As a good habit I would recommend @Infantryman 's implementation in the comment above, which puts the length() call at initialization stage. On top of "less function calls", it also avoids non-trivial infinite loops.Junkojunkyard
@SunnyPun: I'd do that in cases where a) the computation isn't trivial - in this case I'd expect it to be inlined; b) there's any chance of modifying the thing being iterated over. In this case as strings are immutable and we're not changing the value of haystack, I'd use this version.Vacationist
P
62

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

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
Pulley answered 9/11, 2008 at 16:16 Comment(8)
Correct. ReplaceAll(".") would replace any character, not just dot. ReplaceAll("\\.") would have worked. Your solution is more straightforward.Bostwick
jjnguy had actually suggested a replaceAll("[^.]") first, upon seeing my "a.b.c.d".split("\\.").length-1 solution. But after being hit 5 times, I deleted my answer (and his comment).Bostwick
"...now you have two problems" (oblig.) Anyway, I'd bet that there are tens of loops executing in replaceAll() and length(). Well, if it's not visible, it doesn't exist ;o)Thayne
replaceAll uses regex and it's huge for computations it has to do. It's better a simple cycle...Declivous
i don't think it's a good idea to use regex and create a new string for the counting. i would just create a static method that loop every character in the string to count the number.Retaretable
@mingfai: indeed, but the original question is about making a one-liner, and even, without a loop (you can do a loop in one line, but it will be ugly!). Question the question, not the answer... :-)Pulley
I like this answer because it is terse and straight forward.Shopworn
I can't believe a regular expression answer has 37 upvotes. You are all fired!Georginageorgine
F
39
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'.

Ferne answered 9/11, 2008 at 14:48 Comment(2)
I like this one. There's still a loop there, of course, as there has to be.Paly
NB that you'd need to divide this number if you wanted to look for substrings of length > 1Pricecutting
B
36
String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();
Bethel answered 11/10, 2013 at 9:46 Comment(0)
P
32

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.

Piscatorial answered 13/11, 2013 at 19:30 Comment(3)
There is an older solution similar to this one in this post.Elagabalus
Because this solution is really inefficientMarsipobranch
This creates an extra string just to produce a count. No idea why anyone would prefer this over StringUtils if StringUtils is an option. If it's not an option, they should just create a simple for loop in a utility class.Snort
K
27

A shorter example is

String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;
Krys answered 29/11, 2009 at 13:40 Comment(1)
This one seems to have a relatively large overhead, be warned that it may create a lot of small strings. Normally that does not matter much but use with care.Biographer
C
18

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

Cryptograph answered 9/11, 2008 at 14:46 Comment(5)
Unless your string is so long you get an OutOfMemoryError.Overspread
The problem sounds contrived enough to be homework, and if so, this recursion is probably the answer you're being asked to find.Krystin
That uses indexOf, which will loop... but a nice idea. Posting a truly "just recursive" solution in a minute...Vacationist
If it has more occurrences that your available stack slots, you will have a stack overflow exception ;)Peon
Loop is not dangerous. Recursion of uncontrolled depth is really dangerous.Headman
V
16

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.

Vacationist answered 9/11, 2008 at 18:6 Comment(2)
No, tail recursion will probably be in Java 7, but it's not widespread yet. This simple, direct tail recursion could be translated to a loop at compile time, but the Java 7 stuff is actually built-in to the JVM to handle chaining through different methods.Krystin
You'd be more likely to get tail recursion if your method returned a call to itself (including a running total parameter), rather than returning the result of performing an addition.Ddene
E
16

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.

Eyra answered 16/4, 2013 at 9:50 Comment(2)
Giving some love for this one because it is the only one doing a single pass over the string. I DO care about performance .Enchanter
charAt iterates through 16 bit code points not characters! A char in Java is not a character. So this answer implies that there must be no Unicode symbol with a high surrogate being equal to the code point of delim. I am not sure if it is correct for the dot, but in general it might be not correct.Tracytrade
U
12

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;
}
Unstuck answered 11/11, 2008 at 14:20 Comment(0)
F
12

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);
}
Flavor answered 11/1, 2013 at 14:23 Comment(1)
To also count occurences at the end of the string you will have to call split with a negative limit argument like this: return (content.split(target, -1).length - 1);. By default occurences at the end of the string are omitted in the Array resulting from split(). See the DokuApplegate
M
11

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
Mesdemoiselles answered 26/5, 2014 at 16:39 Comment(1)
Using .codePoints() instead of .chars() would then support any Unicode value (including those requiring surrogate pairs)Antitrades
M
10

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
Muley answered 24/5, 2017 at 14:5 Comment(0)
K
9

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));
}
Kaz answered 17/5, 2017 at 9:14 Comment(2)
This snippet does not return the correct amount of dots for a given input "a.b.c."Readus
@Readus Could you please paste your sting in the comment so that we can take a look.Kaz
M
8

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
Mroz answered 3/3, 2012 at 17:54 Comment(2)
wrong code its not working when i try int occurrences = CharacterCounter.countOccurrences("1", "101"); System.out.println(occurrences); // 1Clipclop
I commit a fix for the code that works with the same logicHeavierthanair
L
5

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

Lodgings answered 24/2, 2011 at 11:21 Comment(0)
M
5

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

int noOccurence=string.split("#",-1).length-1;
Melodics answered 19/5, 2016 at 7:59 Comment(3)
Split really creates the array of strings, which consumes much time.Elative
You're right, that's a true concern. In another way it avoids bringing a third-party lib in your project (if not yet done). It depends on what you want to do and what is the performance expectation.Calabro
This solution will NOT include the trailing empty hits, because the argument limit is set to zero in this overloaded split method call. An example: "1##2#3#####".split("#") will only yield an array of size 4 ([0:"1";1:""; 2:"2"; 3:"3"]) instead size 9 ([0:"1"; 1:""; 2:"2"; 3:"3"; 4:""; 5:""; 6:""; 7:""; 8:""]).Jamila
P
5

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

Phasia answered 14/12, 2019 at 5:16 Comment(1)
The problem here is that an array has to be allocated, which is terribly slow.Elative
H
4
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;
}
Headman answered 7/6, 2011 at 15:29 Comment(0)
G
3

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.

Geriatrics answered 9/11, 2008 at 18:19 Comment(2)
I think this is the most elegant solution. Why did you use toCharArray and not charAt directly?Cicada
Looping with charAt at least used to be slower. Might depend on the platform, too. The only way to really find out would be to measure the difference.Geriatrics
T
3
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
Thralldom answered 14/11, 2012 at 23:11 Comment(0)
S
3

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.

Salazar answered 14/1, 2016 at 23:49 Comment(0)
R
3

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.

Radioscope answered 23/6, 2017 at 5:40 Comment(0)
A
3

This is what I use to count the occurrences of a string.

Hope someone finds it helpful.

    private long countOccurrences(String occurrences, char findChar){
        return  occurrences.chars().filter( x -> {
            return x == findChar;
        }).count();
    }
Antigua answered 22/6, 2020 at 12:20 Comment(0)
T
2

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
Thayne answered 11/11, 2008 at 14:39 Comment(0)
D
2

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);
}
Ddene answered 20/3, 2009 at 11:25 Comment(0)
P
2

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?

Piccadilly answered 28/4, 2011 at 4:59 Comment(0)
B
2

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

    }
}
Butterfly answered 2/5, 2013 at 10:56 Comment(0)
A
2
int count = (line.length() - line.replace("str", "").length())/"str".length();
Assiut answered 7/5, 2014 at 12:3 Comment(0)
T
1
 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;
}
Thoroughgoing answered 10/7, 2013 at 8:59 Comment(0)
B
1

Why are you trying to avoid the loop? I mean you can't count the "numberOf" dots without checking every single character of the string, and if you call any function, somehow it will loop. This is, String.replace should do a loop verifying if the string appears so it can replace every single occurrence.

If you're trying to reduce resource usage, you won't do it like that because you're creating a new String just for counting the dots.

Now if we talk about the recursive "enter code here" method, someone said that it will fail due to an OutOfMemmoryException, I think he forgot StackOverflowException.

So my method would be like this (I know it is like the others but, this problem requires the loop):

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;
}
Bohrer answered 5/9, 2013 at 16:6 Comment(0)
B
1

I see a lot of tricks and such being used. Now I'm not against beautiful tricks but personally I like to simply call the methods that are meant to do the work, so I've created yet another answer.

Note that if performance is any issue, use Jon Skeet's answer instead. This one is a bit more generalized and therefore slightly more readable in my opinion (and of course, reusable for strings and patterns).

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;
}
Biographer answered 30/8, 2014 at 16:59 Comment(0)
B
1

a lambda one-liner
w/o the need of an external library.
Creates a map with the count of each character:

Map<Character,Long> counts = "a.b.c.d".codePoints().boxed().collect(
    groupingBy( t -> (char)(int)t, counting() ) );

gets: {a=1, b=1, c=1, d=1, .=3}
the count of a certain character eg. '.' is given over:
counts.get( '.' )

(I also write a lambda solution out of morbid curiosity to find out how slow my solution is, preferably from the man with the 10-line solution.)

Barbour answered 26/11, 2020 at 16:55 Comment(0)
A
0

Try this method:

StringTokenizer stOR = new StringTokenizer(someExpression, "||");
int orCount = stOR.countTokens()-1;
Aweinspiring answered 4/8, 2010 at 18:6 Comment(1)
Downvote from me. It's not returning valid results in all cases, for example if we count 'a' in "a,a,a,a,a" string, it returns 3 instead of 5.Surveillance
T
0

What about below recursive algo.Which is also linear time.

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


}


</i>
Trochophore answered 30/5, 2014 at 20:5 Comment(0)
A
0

Try this code:

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

}
Alien answered 30/8, 2015 at 7:2 Comment(0)
C
0

If you want to count the no. of same character in a string 'SELENIUM' or you want to print the unique characters of the string 'SELENIUM'.

public class Count_Characters_In_String{

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

/******************** OUTPUT **********************/

SELENIUM

SELNIUM

S : 1,E : 2,L : 1,E : 1,N : 1,I : 1,U : 1

Caprine answered 26/4, 2017 at 7:25 Comment(0)
H
0
String[] parts = text.split(".");
int occurances = parts.length - 1;

" It's a great day at O.S.G. Dallas! "
     -- Famous Last Words

Well, it's a case of knowing your Java, especially your basic foundational understanding of the collection classes already available in Java. If you look throughout the entire posting here, there is just about everything short of Stephen Hawking's explanation of the Origin of the Universe, Darwin's paperback on Evolution and Gene Roddenberry's Star Trek cast selection as to why they went with William Shatner short of how to do this quickly and easily...

... need I say anymore?

Harlot answered 29/7, 2017 at 19:7 Comment(4)
Can you add an explanation to this instead of just posting code?Gabor
This creates the parts array, which needs to be allocated and later garbage collected. Completely unnecessary overhead. Try doing this in a tight loop.Elative
Beside shouldn't it be split("\\.") for splitting at dots?Glosso
Besides, if the string is "foo." the result will be the same as if the string was "bar"Readus
C
0

Using Java 8 and a HashMap without any library for counting all the different chars:

private static void countChars(String string) {
    HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
    string.chars().forEach(letter -> hm.put(letter, (hm.containsKey(letter) ? hm.get(letter) : 0) + 1));
    hm.forEach((c, i) -> System.out.println(((char)c.intValue()) + ":" + i));
}
Culverin answered 22/8, 2019 at 10:11 Comment(0)
B
0

use a lambda function which removes all characters to count
the count is the difference of the before-length and after-length

String s = "a.b.c.d";
int count = s.length() - deleteChars.apply( s, "." ).length();  // 3

find deleteChars here


if you have to count the occurrences of more than one character it can be done in one swoop:
eg. for b c and .:

int count = s.length() - deleteChars.apply( s, "bc." ).length();  // 5
Barbour answered 2/10, 2019 at 23:28 Comment(0)
W
0

Here is most simple and easy to understand without using arrays, just by using Hashmap. Also it will calculate whitespaces, number of capital chars and small chars, special characters etc.

import java.util.HashMap;
  //The code by muralidharan  
    public class FindChars {
        
        public static void main(String[] args) {
            
            findchars("rererereerererererererere");
        }
        
        public static void findchars(String s){
            
            HashMap<Character,Integer> k=new HashMap<Character,Integer>();
            for(int i=0;i<s.length();i++){
                if(k.containsKey(s.charAt(i))){
                Integer v =k.get(s.charAt(i));
                k.put(s.charAt(i), v+1);
                }else{
                    k.put(s.charAt(i), 1);
                }
                
            }
            System.out.println(k);
            
        }
    
    }

O/P: {r=12, e=13}

second input:

findchars("The world is beautiful and $#$%%%%%%@@@@ is worst");

O/P: { =7, @=4, a=2, b=1, #=1, d=2, $=2, e=2, %=6, f=1, h=1, i=3, l=2, n=1, o=2, r=2, s=3, T=1, t=2, u=2, w=2}

Whimsey answered 9/4, 2021 at 18:26 Comment(0)
A
0
 public static String encodeMap(String plainText){
        
        Map<Character,Integer> mapResult=new LinkedHashMap<Character,Integer>();
        String result = "";
        for(int i=0;i<plainText.length();i++){
            if(mapResult.containsKey(plainText.charAt(i))){
            Integer v =mapResult.get(plainText.charAt(i));
            mapResult.put(plainText.charAt(i), v+1);
            }else{
                mapResult.put(plainText.charAt(i), 1);
            }
        }
        
        for(Map.Entry<Character, Integer> t : mapResult.entrySet()) {
            result += String.valueOf(t.getKey())+t.getValue();
        }
        
        return result;
        
    }

 public static void main(String args[]) {
        String  plainText = "aaavvfff";
        System.out.println(encodeMap(plainText)); //a3v2f3  
    }
Armhole answered 28/8, 2021 at 17:38 Comment(0)
J
-1
public static void getCharacter(String str){

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


    }
}
Jeffreys answered 1/8, 2018 at 19:22 Comment(2)
A blob of code is not a great answer. Maybe try to expand on this with reasoning, explanation, gotchas, etc.Milstone
Java doesn't use ASCII; char is a UTF-16 code unit. The range is 0..Character.MAX_VALUE. Your algorithm works if the goal is to count occurances of UTF-16 code units.Rosaline
C
-3
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); } }
Cyanite answered 21/11, 2014 at 11:6 Comment(2)
I see this answer is truncated, so perhaps you don't need the following suggestions. But just to be sure: 1) Don't just paste some code. Explain it a bit, tell us why you think it's a good solution. 2) Format your code: stackoverflow.com/editing-helpMailand
Code-only answers are auto-flagged as low quality and as such are discouraged on stackoverflow. In the future please embellish your answer with details and explain why it is a solution to the question. This helps other users. Also - have you never heard of carriage returns??Fulgurous
S
-5

I tried to work out your question with a switch statement but I still required a for loop to parse the string . feel free to comment if I can improve the code

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

}

Scalade answered 19/3, 2015 at 17:7 Comment(1)
This is as far away from one-liner as possible. Terrible.Pellucid

© 2022 - 2024 — McMap. All rights reserved.