620

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

Ivar
  • 6,138
  • 12
  • 49
  • 61
Bart
  • 10,873
  • 7
  • 29
  • 23
  • 1
    Homework? Because otherwise I don't see the requirement to avoid the loop. – PhiLho Nov 09 '08 at 16:13
  • 26
    Not averse to a loop so much as looking for an idiomatic one-liner. – Bart Nov 17 '08 at 14:28
  • 2
    Loops were made for a problem like this, write the loop in a common Utility class then call your freshly minted one liner. – che javara Sep 01 '15 at 21:31
  • Similar question for strings: http://stackoverflow.com/questions/767759/occurrences-of-substring-in-a-string – koppor Apr 16 '17 at 19:41
  • 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. – Bill K May 04 '17 at 17:41
  • Possible duplicate of [Find occurrences of characters in a Java String](https://stackoverflow.com/questions/3763970/find-occurrences-of-characters-in-a-java-string) – thSoft Jan 11 '18 at 14:43
  • @thSoft In the future, please choose the higher upvoted questions/answers as the duplicate target. – Mark Rotteveel Jan 11 '18 at 21:52

48 Answers48

1120

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();
Andreas Wederbrand
  • 38,065
  • 11
  • 68
  • 78
  • 129
    Easiest way. Clever one. And it works on Android, where there is no StringUtils class – Jose_GD Nov 06 '12 at 13:12
  • 47
    This is the best answer. The reason it is the best is because you don't have to import another library. – Alex Spencer Jul 09 '13 at 20:03
  • 5
    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. – lyomi Sep 17 '13 at 05:27
  • 32
    Very practical but ugly as hell. I don't recommend it as it leads to confusing code. – Daniel San Mar 25 '14 at 22:54
  • 36
    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. – RonR Jun 05 '14 at 16:54
  • 4
    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) – Grodriguez Jul 09 '14 at 12:00
  • 6
    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. – Himanshu Aggarwal Oct 20 '14 at 06:52
  • 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? – Jacklynn Nov 06 '14 at 16:15
  • No, String.replace doesn't use regexp. http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replace-char-char- – Andreas Wederbrand Nov 06 '14 at 19:27
  • 34
    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! – Ben Nov 18 '14 at 15:41
  • 6
    String.replace(CharSequnce, CharSequence) does use regexp (look at this OpenJDK source code: http://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: http://goo.gl/2FbcWP – hoat4 Apr 04 '15 at 10:34
  • 2
    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();` – James Oltmans Apr 23 '15 at 00:37
  • 3
    @Grodriguez 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). – Andy Apr 22 '17 at 21:16
  • 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. – Grodriguez Apr 23 '17 at 14:16
  • 1
    Shouldn't this be: int count = (line.length() - line.replace(".", "").length()) / ".".length(); assuming you would want to parameterize the string "."? – mrg Dec 11 '17 at 14:02
  • 1
    Well, this answer is so embarrassing easy, not in a thousand years I would have thought of that... – Max Belli May 14 '18 at 07:02
  • This is very wrong, you're allocating memory to perform counting in a linear scan. – Hardest Sep 17 '20 at 14:48
782

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", ".");
razeeth
  • 11
  • 2
Cowan
  • 37,227
  • 11
  • 66
  • 65
  • 44
    [Guava](https://code.google.com/p/guava-libraries/) equivalent: `int count = CharMatcher.is('.').countIn("a.b.c.d");` ...As [answered by dogbane](http://stackoverflow.com/a/3764170/56285) in a duplicate question. – Jonik Aug 12 '13 at 17:00
  • 29
    Although i will not downvote this, it is (a) requiring 3rd party libs and (b) expensive. – WestCoastProjects Jan 23 '14 at 21:24
  • This only work with spring frame work have to import. – Isuru Madusanka Sep 29 '15 at 10:45
  • 1
    if someone needs it: http://grepcode.com/file/repo1.maven.org/maven2/commons-lang/commons-lang/2.3/org/apache/commons/lang/StringUtils.java – cV2 Nov 27 '15 at 12:54
  • 25
    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. – AbuNassar Oct 05 '16 at 14:58
  • For Maven/Gradle: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.0 – AutonomousApps Feb 15 '17 at 22:55
  • I got a core java solution, check this : https://stackoverflow.com/questions/3763970/find-occurrences-of-characters-in-a-java-string – Banee Ishaque K Jun 24 '17 at 02:02
327

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
Slava Vedenin
  • 58,326
  • 13
  • 40
  • 59
  • The printed strings do not match the ones above, and the order is fastest first which makes lookup tricky at least. Nice answer otherways! – Maarten Bodewes Jun 01 '17 at 11:05
  • 1
    case 2, generalized for codepoints that need more than one UTF-16 code unit: `"123 has 2".codePoints().filter((c) -> c == "".codePointAt(0)).count()` – Tom Blodget Aug 01 '18 at 22:50
  • [Apache Commons's `StringUtils.countMatches`](https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java#L1392-L1423) loops over indices and uses `charAt`; [Spring Framework's `StringUtils.countOccurencesOf`](https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/util/StringUtils.java#L377-L395) uses `indexOf` repeatedly. ([OpenJDK's `String.indexOf`](https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/String.java#l1493) basically uses `charAt` in a loop.) – Solomon Ucko Aug 18 '20 at 20:29
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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 6
    for (int i=0,l=haystack.length(); i < l; i++) be kind to your stack – Chris Nov 29 '09 at 13:43
  • 12
    (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.) – Jon Skeet Nov 29 '09 at 14:51
  • 3
    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. – ShuggyCoUk Nov 30 '09 at 11:15
  • I think @Chris 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. – sulai Jun 12 '14 at 13:37
  • 5
    @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. – Jon Skeet Jun 12 '14 at 13:39
  • 1
    Probably @sulai 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 @ShuggyCoUk a few comments up. – JKillian Jul 30 '14 at 02:19
  • 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. – njlarsson Mar 01 '16 at 15:32
  • 1
    @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. – Jon Skeet Mar 01 '16 at 16:01
  • @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. – njlarsson Mar 02 '16 at 08:33
  • nice `needle` in a `haystack` analogy ;) –  May 18 '17 at 05:48
  • (Sorry for commenting on an old post) As a good habit I would recommend @Chris '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](https://www.testdome.com/questions/javascript/loop/11100?type=FromTest&generatorId=23&questionIds=11100%2C9699%2C12481%2C11942). – Sunny Pun Dec 03 '18 at 06:01
  • @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. – Jon Skeet Dec 03 '18 at 07:08
62

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

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
PhiLho
  • 40,535
  • 6
  • 96
  • 134
  • Correct. ReplaceAll(".") would replace any character, not just dot. ReplaceAll("\\.") would have worked. Your solution is more straightforward. – VonC Nov 09 '08 at 16:20
  • 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). – VonC Nov 09 '08 at 16:24
  • "...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) – Piskvor left the building Aug 25 '10 at 11:22
  • replaceAll uses regex and it's huge for computations it has to do. It's better a simple cycle... – robob Apr 20 '11 at 12:50
  • 2
    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. – mingfai Apr 23 '11 at 23:14
  • 1
    @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... :-) – PhiLho Apr 26 '11 at 17:25
  • I like this answer because it is terse and straight forward. –  Jun 22 '12 at 12:25
  • I can't believe a regular expression answer has 37 upvotes. You are all fired! – MK. Jan 02 '13 at 20:36
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'.

Community
  • 1
  • 1
Mladen Prajdic
  • 15,457
  • 2
  • 43
  • 51
35
String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();
Martin Andersson
  • 18,072
  • 9
  • 87
  • 115
fubo
  • 44,811
  • 17
  • 103
  • 137
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.

mlchen850622
  • 668
  • 6
  • 7
  • 5
    There is an older solution similar to this one in this post. – JCalcines Feb 05 '14 at 09:24
  • 8
    Because this solution is really inefficient – András May 14 '15 at 09:41
  • 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. – crush May 28 '16 at 20:15
27

A shorter example is

String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 4
    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. – Maarten Bodewes Aug 30 '14 at 16:51
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

Yonatan Maman
  • 2,428
  • 1
  • 24
  • 34
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.

0xCAFEBABE
  • 5,576
  • 5
  • 34
  • 59
  • Giving some love for this one because it is the only one doing a single pass over the string. I DO care about performance . – WestCoastProjects Jan 22 '14 at 20:19
  • 2
    `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. – ceving Jul 22 '14 at 17:25
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.

oshai
  • 14,865
  • 26
  • 84
  • 140
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 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. – erickson Nov 10 '08 at 20:11
  • 3
    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. – Stephen Denne Mar 20 '09 at 10:56
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);
}
KannedFarU
  • 305
  • 3
  • 9
  • 5
    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 [Doku](http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#split%28java.lang.String%29) – vlz May 04 '14 at 12:08
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;
}
Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
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
Alexis C.
  • 91,686
  • 21
  • 171
  • 177
  • Using `.codePoints()` instead of `.chars()` would then support any Unicode value (including those requiring surrogate pairs) – Luke Usherwood Aug 14 '14 at 14:40
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
gil.fernandes
  • 12,978
  • 5
  • 63
  • 76
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));
}
Smart Manoj
  • 5,230
  • 4
  • 34
  • 59
Amar Magar
  • 840
  • 1
  • 11
  • 15
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
Benny Code
  • 51,456
  • 28
  • 233
  • 198
  • wrong code its not working when i try int occurrences = CharacterCounter.countOccurrences("1", "101"); System.out.println(occurrences); // 1 – jayesh Jan 20 '14 at 06:32
  • I commit a fix for the code that works with the same logic – MaanooAk Jul 27 '17 at 07:06
5

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

int noOccurence=string.split("#",-1).length-1;
Smart Manoj
  • 5,230
  • 4
  • 34
  • 59
user3322553
  • 239
  • 2
  • 8
  • Split really creates the array of strings, which consumes much time. – Palec May 19 '16 at 17:03
  • 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. – Benj Jun 14 '16 at 07:23
  • 3
    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:""]`). – klaar Aug 31 '16 at 15:05
5

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

Michal Kordas
  • 10,475
  • 7
  • 58
  • 103
user496208
  • 69
  • 1
  • 2
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");

Saharcasm
  • 148
  • 1
  • 8
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;
}
Hardest
  • 348
  • 1
  • 3
  • 7
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
Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
kassim
  • 39
  • 1
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.

tcurdt
  • 14,518
  • 10
  • 57
  • 72
  • I think this is the most elegant solution. Why did you use toCharArray and not charAt directly? – Panayotis May 31 '17 at 08:29
  • 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. – tcurdt May 31 '17 at 14:00
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.

bdkosher
  • 5,753
  • 2
  • 33
  • 40
Christoph Zabinski
  • 327
  • 2
  • 5
  • 17
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.

Donald Raab
  • 6,458
  • 2
  • 36
  • 44
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();
    }
IonKat
  • 436
  • 6
  • 12
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);
        }

    }
}
Salvatorelab
  • 11,614
  • 6
  • 53
  • 80
Shubham
  • 310
  • 4
  • 16
2
int count = (line.length() - line.replace("str", "").length())/"str".length();
Not a bug
  • 4,286
  • 2
  • 40
  • 80
Shaban
  • 113
  • 2
  • 11
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
Piskvor left the building
  • 91,498
  • 46
  • 177
  • 222
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?

Darryl Price
  • 21
  • 1
  • 2
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);
}
Stephen Denne
  • 36,219
  • 10
  • 45
  • 60
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;
}
Adrian
  • 79
  • 4
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;
}
Syon
  • 7,205
  • 5
  • 36
  • 40
Sergio
  • 11
  • 1
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;
}
Community
  • 1
  • 1
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
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.)

Kaplan
  • 2,572
  • 13
  • 14
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>
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);
    }

}
Yurets
  • 3,999
  • 17
  • 54
  • 74
0

Try this method:

StringTokenizer stOR = new StringTokenizer(someExpression, "||");
int orCount = stOR.countTokens()-1;
Somnath Muluk
  • 55,015
  • 38
  • 216
  • 226
  • 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. – Greg Witczak May 28 '15 at 15:05
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

Smart Manoj
  • 5,230
  • 4
  • 34
  • 59
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?

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));
}
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
Kaplan
  • 2,572
  • 13
  • 14
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}

Murali
  • 774
  • 6
  • 12
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  
    }
hadialaoui
  • 71
  • 1
  • 4
-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]);
        }


    }
}
Smart Manoj
  • 5,230
  • 4
  • 34
  • 59
  • A blob of code is not a great answer. Maybe try to expand on this with reasoning, explanation, gotchas, etc. –  Aug 01 '18 at 19:44
  • 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. – Tom Blodget Aug 01 '18 at 22:47
-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); } }
tom redfern
  • 30,562
  • 14
  • 91
  • 126
  • 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: http://stackoverflow.com/editing-help – cornuz Nov 21 '14 at 11:16
  • 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?? – tom redfern Nov 21 '14 at 11:47
-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);
}

}