How do I count the number of occurrences of a char in a String?
JavaStringJava Problem Overview
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).
Java Solutions
Solution 1 - Java
How about this. It doesn't use regexp underneath so should be faster than some of the other solutions and won't use a loop.
int count = line.length() - line.replace(".", "").length();
Solution 2 - Java
My 'idiomatic one-liner' for this is:
int count = StringUtils.countMatches("a.b.c.d", ".");
Why write it yourself when it's already in commons lang?
Spring Framework's oneliner for this is:
int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");
Solution 3 - Java
Summarize other answer and what I know all ways to do this using a one-liner:
String testString = "a.b.c.d";
-
Using Apache Commons
int apache = StringUtils.countMatches(testString, "."); System.out.println("apache = " + apache);
-
Using Spring Framework's
int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, "."); System.out.println("spring = " + spring);
-
Using replace
int replace = testString.length() - testString.replace(".", "").length(); System.out.println("replace = " + replace);
-
Using replaceAll (case 1)
int replaceAll = testString.replaceAll("[^.]", "").length(); System.out.println("replaceAll = " + replaceAll);
-
Using replaceAll (case 2)
int replaceAllCase2 = testString.length() - testString.replaceAll("\.", "").length(); System.out.println("replaceAll (second case) = " + replaceAllCase2);
-
Using split
int split = testString.split("\.",-1).length-1; System.out.println("split = " + split);
-
Using Java8 (case 1)
long java8 = testString.chars().filter(ch -> ch =='.').count(); System.out.println("java8 = " + java8);
-
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);
-
Using StringTokenizer
int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);
From comment: Be carefull for the StringTokenizer, for a.b.c.d it will work but for a...b.c....d or ...a.b.c.d or a....b......c.....d... or etc. it will not work. It just will count for . between characters just once
More info in github
Perfomance test (using JMH, mode = AverageTime, score 0.010
better then 0.351
):
Benchmark Mode Cnt Score Error Units
1. countMatches avgt 5 0.010 ± 0.001 us/op
2. countOccurrencesOf avgt 5 0.010 ± 0.001 us/op
3. stringTokenizer avgt 5 0.028 ± 0.002 us/op
4. java8_1 avgt 5 0.077 ± 0.005 us/op
5. java8_2 avgt 5 0.078 ± 0.003 us/op
6. split avgt 5 0.137 ± 0.009 us/op
7. replaceAll_2 avgt 5 0.302 ± 0.047 us/op
8. replace avgt 5 0.303 ± 0.034 us/op
9. replaceAll_1 avgt 5 0.351 ± 0.045 us/op
Solution 4 - Java
Sooner or later, something has to loop. It's far simpler for you to write the (very simple) loop than to use something like split
which is much more powerful than you need.
By all means encapsulate the loop in a separate method, e.g.
public static int countOccurrences(String haystack, char needle)
{
int count = 0;
for (int i=0; i < haystack.length(); i++)
{
if (haystack.charAt(i) == needle)
{
count++;
}
}
return count;
}
Then you don't need have the loop in your main code - but the loop has to be there somewhere.
Solution 5 - Java
I had an idea similar to Mladen, but the opposite...
String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
Solution 6 - Java
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();
ReplaceAll(".") would replace all characters.
PhiLho's solution uses ReplaceAll("[^.]",""), which does not need to be escaped, since [.] represents the character 'dot', not 'any character'.
Solution 7 - Java
String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();
Solution 8 - Java
My 'idiomatic one-liner' solution:
int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();
Have no idea why a solution that uses StringUtils is accepted.
Solution 9 - Java
A shorter example is
String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;
Solution 10 - Java
here is a solution without a loop:
public static int countOccurrences(String haystack, char needle, int i){
return ((i=haystack.indexOf(needle, i)) == -1)?0:1+countOccurrences(haystack, needle, i+1);}
System.out.println("num of dots is "+countOccurrences("a.b.c.d",'.',0));
well, there is a loop, but it is invisible :-)
-- Yonatan
Solution 11 - Java
Okay, inspired by Yonatan's solution, here's one which is purely recursive - the only library methods used are length()
and charAt()
, neither of which do any looping:
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int index)
{
if (index >= haystack.length())
{
return 0;
}
int contribution = haystack.charAt(index) == needle ? 1 : 0;
return contribution + countOccurrences(haystack, needle, index+1);
}
Whether recursion counts as looping depends on which exact definition you use, but it's probably as close as you'll get.
I don't know whether most JVMs do tail-recursion these days... if not you'll get the eponymous stack overflow for suitably long strings, of course.
Solution 12 - Java
I don't like the idea of allocating a new string for this purpose. And as the string already has a char array in the back where it stores it's value, String.charAt() is practically free.
for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))
does the trick, without additional allocations that need collection, in 1 line or less, with only J2SE.
Solution 13 - Java
Inspired by Jon Skeet, a non-loop version that wont blow your stack. Also useful starting point if you want to use the fork-join framework.
public static int countOccurrences(CharSequeunce haystack, char needle) {
return countOccurrences(haystack, needle, 0, haystack.length);
}
// Alternatively String.substring/subsequence use to be relatively efficient
// on most Java library implementations, but isn't any more [2013].
private static int countOccurrences(
CharSequence haystack, char needle, int start, int end
) {
if (start == end) {
return 0;
} else if (start+1 == end) {
return haystack.charAt(start) == needle ? 1 : 0;
} else {
int mid = (end+start)>>>1; // Watch for integer overflow...
return
countOccurrences(haystack, needle, start, mid) +
countOccurrences(haystack, needle, mid, end);
}
}
(Disclaimer: Not tested, not compiled, not sensible.)
Perhaps the best (single-threaded, no surrogate-pair support) way to write it:
public static int countOccurrences(String haystack, char needle) {
int count = 0;
for (char c : haystack.toCharArray()) {
if (c == needle) {
++count;
}
}
return count;
}
Solution 14 - Java
Not sure about the efficiency of this, but it's the shortest code I could write without bringing in 3rd party libs:
public static int numberOf(String target, String content)
{
return (content.split(target).length - 1);
}
Solution 15 - Java
With [tag:java-8] you could also use streams to achieve this. Obviously there is an iteration behind the scenes, but you don't have to write it explicitly!
public static long countOccurences(String s, char c){
return s.chars().filter(ch -> ch == c).count();
}
countOccurences("a.b.c.d", '.'); //3
countOccurences("hello world", 'l'); //3
Solution 16 - Java
Also possible to use reduce in Java 8 to solve this problem:
int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);
Output:
3
Solution 17 - Java
The simplest way to get the answer is as follow:
public static void main(String[] args) {
String string = "a.b.c.d";
String []splitArray = string.split("\\.",-1);
System.out.println("No of . chars is : " + (splitArray.length-1));
}
Solution 18 - Java
Complete sample:
public class CharacterCounter
{
public static int countOccurrences(String find, String string)
{
int count = 0;
int indexOf = 0;
while (indexOf > -1)
{
indexOf = string.indexOf(find, indexOf + 1);
if (indexOf > -1)
count++;
}
return count;
}
}
Call:
int occurrences = CharacterCounter.countOccurrences("l", "Hello World.");
System.out.println(occurrences); // 3
Solution 19 - Java
In case you're using Spring framework, you might also use "StringUtils" class. The method would be "countOccurrencesOf".
Solution 20 - Java
You can use the split()
function in just one line code
int noOccurence=string.split("#",-1).length-1;
Solution 21 - Java
A much easier solution would be to just the split the string based on the character you're matching it with.
For instance,
int getOccurences(String characters, String string) { String[] words = string.split(characters); return words.length - 1; }
This will return 4 in the case of:
getOccurences("o", "something about a quick brown fox");
Solution 22 - Java
public static int countOccurrences(String container, String content){
int lastIndex, currIndex = 0, occurrences = 0;
while(true) {
lastIndex = container.indexOf(content, currIndex);
if(lastIndex == -1) {
break;
}
currIndex = lastIndex + content.length();
occurrences++;
}
return occurrences;
}
Solution 23 - Java
While methods can hide it, there is no way to count without a loop (or recursion). You want to use a char[] for performance reasons though.
public static int count( final String s, final char c ) {
final char[] chars = s.toCharArray();
int count = 0;
for(int i=0; i<chars.length; i++) {
if (chars[i] == c) {
count++;
}
}
return count;
}
Using replaceAll (that is RE) does not sound like the best way to go.
Solution 24 - Java
import java.util.Scanner;
class apples {
public static void main(String args[]) {
Scanner bucky = new Scanner(System.in);
String hello = bucky.nextLine();
int charCount = hello.length() - hello.replaceAll("e", "").length();
System.out.println(charCount);
}
}// COUNTS NUMBER OF "e" CHAR´s within any string input
Solution 25 - Java
Well, with a quite similar task I stumbled upon this Thread. I did not see any programming language restriction and since groovy runs on a java vm: Here is how I was able to solve my Problem using Groovy.
"a.b.c.".count(".")
done.
Solution 26 - Java
Using Eclipse Collections
int count = Strings.asChars("a.b.c.d").count(c -> c == '.');
If you have more than one character to count, you can use a CharBag
as follows:
CharBag bag = Strings.asChars("a.b.c.d").toBag();
int count = bag.occurrencesOf('.');
Note: I am a committer for Eclipse Collections.
Solution 27 - Java
Somewhere in the code, something has to loop. The only way around this is a complete unrolling of the loop:
int numDots = 0;
if (s.charAt(0) == '.') {
numDots++;
}
if (s.charAt(1) == '.') {
numDots++;
}
if (s.charAt(2) == '.') {
numDots++;
}
...etc, but then you're the one doing the loop, manually, in the source editor - instead of the computer that will run it. See the pseudocode:
create a project
position = 0
while (not end of string) {
write check for character at position "position" (see above)
}
write code to output variable "numDots"
compile program
hand in homework
do not think of the loop that your "if"s may have been optimized and compiled to
Solution 28 - Java
Here is a slightly different style recursion solution:
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int accumulator)
{
if (haystack.length() == 0) return accumulator;
return countOccurrences(haystack.substring(1), needle, haystack.charAt(0) == needle ? accumulator + 1 : accumulator);
}
Solution 29 - Java
Why not just split on the character and then get the length of the resulting array. array length will always be number of instances + 1. Right?
Solution 30 - Java
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);
}
}
}
Solution 31 - Java
int count = (line.length() - line.replace("str", "").length())/"str".length();
Solution 32 - Java
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;
}
Solution 33 - Java
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;
}
Solution 34 - Java
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;
}
Solution 35 - Java
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();
}
Solution 36 - Java
Try this method:
StringTokenizer stOR = new StringTokenizer(someExpression, "||");
int orCount = stOR.countTokens()-1;
Solution 37 - Java
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>
Solution 38 - Java
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);
}
}
Solution 39 - Java
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
Solution 40 - Java
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?
Solution 41 - Java
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));
}
Solution 42 - Java
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
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
Solution 43 - Java
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.)
Solution 44 - Java
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}
Solution 45 - Java
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
}
Solution 46 - Java
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]);
}
}
}
Solution 47 - Java
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); } }
Solution 48 - Java
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);
}
}