[java] How to count frequency of characters in a string?

I need to write some kind of loop that can count the frequency of each letter in a string.
For example: "aasjjikkk" would count 2 'a', 1 's', 2 'j', 1 'i', 3 'k'. Ultimately id like these to end up in a map with the character as the key and the count as the value. Any good idea how to do this?

This question is related to java string key-value

The answer is


The shorted possible code using a HashMap. (With no forceful line saves)

private static Map<Character, Integer> findCharacterFrequency(String str) {

        Map<Character, Integer> map = new HashMap<>();

        for (char ch : str.toCharArray()) {
            /* Using getOrDefault(), since Java1.8 */
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }
        return map;
    }

*import java.util.ArrayList;
import java.util.Collections;

public class Freq {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String temp="zsaaqaaaaaaaabbbbbcc";
    List<String> temp1= new ArrayList<String> ();
    ArrayList<Integer>freq=new ArrayList<Integer>();
    for(int i=0;i<temp.length()-1;i++)
    {       
        temp1.add(Character.toString(temp.charAt(i)));      
    }
    Set<String> uniqset=new HashSet<String>(temp1);
    for(String s:uniqset)
    {
        freq.add(Collections.frequency(temp1, s));
        System.out.println(s+" -->>"+Collections.frequency(temp1, s));
    }
    }

}
           ------Output-------
       a -->>10
       b -->>5
       c -->>1
       q -->>1
       s -->>1
       z -->>1

Use collections frequency method to count frequency of char*


Another way using map merge method

   Map<Character, Integer> map = new HashMap<>();
   String s = "aasjjikkk";
    for (int i = 0; i < s.length(); i++) {
        map.merge(s.charAt(i), 1, (l, r) -> l + r);

Please try the given code below, hope it will helpful to you,

import java.util.Scanner;

class String55 {
    public static int frequency(String s1,String s2)
    {

        int count=0;
        char ch[]=s1.toCharArray();
        char ch1[]=s2.toCharArray();
        for (int i=0;i<ch.length-1; i++)
        {



                int k=i;

                int j1=i+1;
                int j=0;
                int j11=j;
                int j2=j+1;
                {
                    while(k<ch.length && j11<ch1.length && ch[k]==ch1[j11])
                    {
                    k++;
                    j11++;

                    }


                int l=k+j1;
                int m=j11+j2;
                if( l== m)
                {
                    count=1;
                    count++;
                }





        }
        }
        return count;


    }
    public static void main (String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.println("enter the pattern");
        String s1=sc.next();
            System.out.println("enter the String");
            String s2=sc.next();
            int res=frequency(s1, s2);
            System.out.println("FREQUENCY==" +res);

    }
}

SAMPLE OUTPUT: enter the pattern man enter the String dhimanman FREQUENCY==2

Thank-you.Happy coding.


String s = "aaaabbbbcccddddd";
Map<Character, Integer> map = new HashMap<>();

Using one line in Java8

s.chars().forEach(e->map.put((char)e, map.getOrDefault((char)e, 0) + 1));

#From C language

 #include<stdio.h>`
 #include <string.h>`
  int main()
{
    char s[1000];  
    int  i,j,k,count=0,n;
    printf("Enter  the string : ");
    gets(s);
    for(j=0;s[j];j++);
    n=j; 
    printf(" frequency count character in string:\n");
    for(i=0;i<n;i++)  
    {
        count=1;
        if(s[i])
        {
        
          for(j=i+1;j<n;j++)  
          {   
            
            if(s[i]==s[j])
            {
                 count++;
                 s[j]='\0';
            }
          }  
          printf(" '%c' = %d \n",s[i],count);
       }
    } 
    return 0;
}

Uffh. Don't you think this is the simplest solution?

    char inputChar = '|';
    int freq = "|fd|fdfd|f dfd|fd".replaceAll("[^" + inputChar +"]", "").length();
    System.out.println("freq " + freq);

Using the stream API as of JDK-8:

Map<Character, Long> frequency =
            str.chars()
               .mapToObj(c -> (char)c)
               .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

or if you want the keys as Integers:

Map<Character, Integer> frequency =
            str.chars()
               .mapToObj(c -> (char)c)
               .collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(c -> 1)));

Another variant:

Map<Character, Integer> frequency = 
            str.chars()
               .mapToObj(c -> (char)c)
               .collect(Collectors.toMap(Function.identity(), c -> 1, Math::addExact));

You can use a CharAdapter and a CharBag from Eclipse Collections and avoid boxing to Character and Integer.

CharBag bag = Strings.asChars("aasjjikkk").toBag();

Assert.assertEquals(2, bag.occurrencesOf('a'));
Assert.assertEquals(1, bag.occurrencesOf('s'));
Assert.assertEquals(2, bag.occurrencesOf('j'));
Assert.assertEquals(1, bag.occurrencesOf('i'));
Assert.assertEquals(3, bag.occurrencesOf('k'));

Note: I am a committer for Eclipse Collections.


Since there was no Java 8 solution, thought of posting one. Also, this solution is much neater, readable and concise than some of the other solutions mentioned here.

String string = "aasjjikkk";

Map<Character, Long> characterFrequency = string.chars()  // creates an IntStream
    .mapToObj(c -> (char) c) // converts the IntStream to Stream<Character>
    .collect(Collectors.groupingBy(c -> c, Collectors.counting())); // creates a
                                                                    // Map<Character, Long> 
                                                                    // where the Long is
                                                                    // the frequency

We can use frequency method of Collections class for this. Split the string into string array. Use HashSet to remove duplicates and check frequency of each object in HashSet using frequency method of Collections

void usingCollections(){

  String input = "cuttack";

  String [] stringArray = input.split("");

  Set<String> s = new HashSet(Arrays.asList(stringArray));

  for(String abc : s){

    System.out.println (abc + ":"+Collections.frequency(Arrays.asList(stringArray),abc));

  }
}

This is more Effective way to count frequency of characters in a string

public class demo {
    public static void main(String[] args) {
        String s = "babdcwertyuiuygf";
        Map<Character, Integer> map = new TreeMap<>();
        s.chars().forEach(e->map.put((char)e, map.getOrDefault((char)e, 0) + 1));
        StringBuffer myValue = new StringBuffer();
        String myMapKeyValue = "";
        for (Map.Entry<Character, Integer> entry : map.entrySet()) {
            myMapKeyValue = Character.toString(entry.getKey()).concat(
                Integer.toString(entry.getValue()));
            myValue.append(myMapKeyValue);
        }
        System.out.println(myValue);
    }
}

There is one more option and it looks quite nice. Since java 8 there is new method merge java doc

  public static void main(String[] args) {
    String s = "aaabbbcca";

    Map<Character, Integer> freqMap = new HashMap<>();
    for (int i = 0; i < s.length(); i++) {
        Character c = s.charAt(i);
        freqMap.merge(c, 1, (a, b) -> a + b);
    }
    freqMap.forEach((k, v) -> System.out.println(k + " and " + v));
}

Or even cleaner with ForEach

       for (Character c : s.toCharArray()) {
            freqMapSecond.merge(c, 1, Integer::sum);
           }

If this does not need to be super-fast just create an array of integers, one integer for each letter (only alphabetic so 2*26 integers? or any binary data possible?). go through the string one char at a time, get the index of the responsible integer (e.g. if you only have alphabetic chars you can have 'A' be at index 0 and get that index by subtracting any 'A' to 'Z' by 'A' just as an example of how you can get reasonably fast indices) and increment the value in that index.

There are various micro-optimizations to make this faster (if necessary).


You can use a Hashtable with each character as the key and the total count becomes the value.

Hashtable<Character,Integer> table = new Hashtable<Character,Integer>();
String str = "aasjjikkk";
for( c in str ) {
    if( table.get(c) == null )
        table.put(c,1);
    else
        table.put(c,table.get(c) + 1);
}

for( elem in table ) {
    println "elem:" + elem;
}

Well, two ways come to mind and it depends on your preference:

  1. Sort the array by characters. Then, counting each character becomes trivial. But you will have to make a copy of the array first.

  2. Create another integer array of size 26 (say freq) and str is the array of characters.

    for(int i = 0; i < str.length; i ++)

    freq[str[i] - 'a'] ++; //Assuming all characters are in lower case

So the number of 'a' 's will be stored at freq[0] and the number of 'z' 's will be at freq[25]


package com.rishi.zava;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class ZipString {
    public static void main(String arg[]) {
        String input = "aaaajjjgggtttssvvkkllaaiiikk";
        int len = input.length();
        Map<Character, Integer> zip = new HashMap<Character, Integer>();
        for (int j = 0; len > j; j++) {
            int count = 0;
            for (int i = 0; len > i; i++) {
                if (input.charAt(j) == input.charAt(i)) {
                    count++;
                }
            }
            zip.put(input.charAt(j), count);
        }
        StringBuffer myValue = new StringBuffer();
        String myMapKeyValue = "";
        for (Entry<Character, Integer> entry : zip.entrySet()) {
            myMapKeyValue = Character.toString(entry.getKey()).concat(
                    Integer.toString(entry.getValue()));
            myValue.append(myMapKeyValue);
        }
        System.out.println(myValue);
    }
}

Input = aaaajjjgggtttssvvkkllaaiiikk

Output = a6s2t3v2g3i3j3k4l2


A concise way to do this is:

Map<Character,Integer> frequencies = new HashMap<>();
for (char ch : input.toCharArray()) 
   frequencies.put(ch, frequencies.getOrDefault(ch, 0) + 1);

We use a for-each to loop through every character. The frequencies.getOrDefault() gets value if key is present or returns(as default) its second argument.


import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;


public class FrequenceyOfCharacters {

    public static void main(String[] args) {
        System.out.println("Please enter the string to count each character frequencey: ");
        Scanner sc=new  Scanner(System.in);
        String s =sc.nextLine();
        String input = s.replaceAll("\\s",""); // To remove space.
        frequenceyCount(input);
        
        
    }

    private static void frequenceyCount(String input) {
        
        Map<Character,Integer> hashCount=new HashMap<>();
        Character c;
        for(int i=0; i<input.length();i++)
        {
           c =input.charAt(i);
           if(hashCount.get(c)!=null){
               hashCount.put(c, hashCount.get(c)+1);
           }else{
               hashCount.put(c, 1);
           }
        }
        Iterator it = hashCount.entrySet().iterator();
        System.out.println("char : frequency");
        while (it.hasNext()) {
            Map.Entry pairs = (Map.Entry)it.next();
            System.out.println(pairs.getKey() + " : " + pairs.getValue());
            it.remove(); 
        }
        
    }

}

You can use a Multiset (from guava). It will give you the count for each object. For example:

Multiset<Character> chars = HashMultiset.create();
for (int i = 0; i < string.length(); i++) {
    chars.add(string.charAt(i));
}

Then for each character you can call chars.count('a') and it returns the number of occurrences


package com.dipu.string;

import java.util.HashMap;
import java.util.Map;

public class RepetativeCharInString {
    public static void main(String[] args) {
        String data = "aaabbbcccdddffffrss";
        char[] charArray = data.toCharArray();
        Map<Character, Integer> map = new HashMap<>();
        for (char c : charArray) {
            if (map.containsKey(c)) {
                map.put(c, map.get(c) + 1);
            } else {
                map.put(c, 1);
            }
        }
        System.out.println(map);

    }
}

Here is another solution, dodgy as it may be.

public char getNumChar(String s) {
    char[] c = s.toCharArray();
    String alphabet = "abcdefghijklmnopqrstuvwxyz";
    int[] countArray = new int[26];
    for (char x : c) {
        for (int i = 0; i < alphabet.length(); i++) {
            if (alphabet.charAt(i) == x) {
                countArray[i]++;
            }
        }
    }

    java.util.HashMap<Integer, Character> countList = new java.util.HashMap<Integer, Character>();

    for (int i = 0; i < 26; i++) {
        countList.put(countArray[i], alphabet.charAt(i));
    }
    java.util.Arrays.sort(countArray);
    int max = countArray[25];
    return countList.get(max);
}

import java.io.FileInputStream;
import java.util.HashSet;
import java.util.Iterator;
public class CountFrequencyOfCharater {
public static void main(String args[]) throws Exception
{
    HashSet hs=new HashSet();
    String str="hey how are you?";
    char arr[]=new char[str.length()];
    for(int i=0;i<str.length();i++)
    {
        arr[i]=str.charAt(i);
    }
    for(int j=0;j<str.length();j++)
    {
        int c=0;
        for(int k=0;k<str.length();k++)
        {
            if(arr[j]==arr[k])
            c++;
        }
        hs.add(arr[j]+"="+c+",");
    }
        Iterator it=hs.iterator();
        while(it.hasNext())
        {
             System.out.print(it.next());
        }
  }
}

import java.util.*;
class Charfrequency
{
 public static void main(String a[]){

        Scanner sc=new Scanner(System.in);
        System.out.println("Enter Your String :");
        String s1=sc.nextLine();
        int count,j=1;
        char var='a';
        char ch[]=s1.toCharArray();
        while(j<=26)
        {
           count=0;
                for(int i=0; i<s1.length(); i++)
                {
                    if(ch[i]==var || ch[i]==var-32)
                    {
                        count++;
                    }
                }
                if(count>0){
                System.out.println("Frequency of "+var+" is "+count);
                }
                var++;
                j++;
        }
 }
}

This is similar to xunil154's answer, except that a string is made a char array and a linked hashmap is used to maintain the insertion order of the characters.

String text = "aasjjikkk";
char[] charArray = text.toCharArray();
Map<Character, Integer> freqList = new LinkedHashMap<Character, Integer>();

        for(char key : charArray) {
            if(freqList.containsKey(key)) {
               freqList.put(key, freqList.get(key) + 1);
            } else
                freqList.put(key, 1);
        }

Here is a solution:

Define your own Pair:

public class Pair
{
    private char letter;
    private int count;
    public Pair(char letter, int count)
    {
        this.letter = letter;
        this.count= count;
    }
    public char getLetter(){return key;}
    public int getCount(){return count;}
}

Then you could do:

public static Pair countCharFreq(String s)
{
    String temp = s;
    java.util.List<Pair> list = new java.util.ArrayList<Pair>();
    while(temp.length() != 0)
    {
        list.add(new Pair(temp.charAt(0), countOccurrences(temp, temp.charAt(0))));
        temp.replaceAll("[" + temp.charAt(0) +"]","");
    }
}

public static int countOccurrences(String s, char c)
{
    int count = 0;
    for(int i = 0; i < s.length(); i++)
    {
        if(s.charAt(i) == c) count++;
    }
    return count;
}

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to key-value

Iterate through dictionary values? How can I get key's value from dictionary in Swift? How to add a new object (key-value pair) to an array in javascript? How to search if dictionary value contains certain string with Python Python: How to check if keys exists and retrieve value from Dictionary in descending priority How do you create a dictionary in Java? how to prevent adding duplicate keys to a javascript array How to update value of a key in dictionary in c#? How to create dictionary and add key–value pairs dynamically? How to count frequency of characters in a string?