Core Java

Count Character Occurrences in Java Using HashMap

Counting the occurrences of characters in a string is a problem that can be solved efficiently using a HashMap data structure in Java. This article will walk you through different ways to implement character frequency counting using HashMap.

1. Why Use HashMap for Character Counting?

A HashMap provides an efficient method for storing key-value pairs. For character counting:

  • The key is the character.
  • The value is the number of times the character appears.

HashMaps offer average constant-time complexity (O(1)) for insertion and retrieval operations, making them ideal for frequency counting tasks.

2. Basic HashMap Implementation

The most straightforward way to count character occurrences in a string is by using a HashMap. In this approach, we iterate through each character of the input string and use the character as the key in the map. Each time we encounter a character, we increment its associated count.

public class CharFrequencyCounter {

    public static Map<Character, Integer> countCharacters(String input) {
        Map<Character, Integer> charCountMap = new HashMap<>();

        for (char ch : input.toCharArray()) {
            if (Character.isWhitespace(ch)) continue; // Optional: Skip spaces
            charCountMap.put(ch, charCountMap.getOrDefault(ch, 0) + 1);
        }

        return charCountMap;
    }

    public static void main(String[] args) {
        String text = "javacodegeeks";

        Map<Character, Integer> result = countCharacters(text);

        result.forEach((key, value) -> System.out.println(key + ": " + value));
    }
}

The toCharArray() method is used to convert the input string into a character array, allowing easy iteration over each character. For every character in the array, getOrDefault(ch, 0) checks if the character is already present in the map; if it is, it retrieves the existing count, otherwise it returns 0. The put() method then updates the map with the new frequency by incrementing the count.

When you run the code with the input "javacodegeeks", the output will display each character along with the number of times it appears.

a: 2
c: 1
s: 1
d: 1
e: 3
v: 1
g: 1
j: 1
k: 1
o: 1

Case-Insensitive Counting with Non-Letter Characters Filtered Out

This version ignores case differences between characters.

public class CaseInsensitiveCounter {
   
    public static Map<Character, Integer> countCharacters(String input) {
        Map<Character, Integer> map = new HashMap<>();

        for (char ch : input.toLowerCase().toCharArray()) {
            if (!Character.isLetter(ch)) continue; // Optional: Only letters
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }

        return map;
    }

    public static void main(String[] args) {
        String input = "Java Programming 2";

        Map<Character, Integer> result = countCharacters(input);
        result.forEach((k, v) -> System.out.println(k + ": " + v));
    }
}

The input string is first converted to lowercase using toLowerCase() to ensure that character counting is case-insensitive. Then, non-letter characters are filtered out by checking each character with Character.isLetter(), so only alphabetical characters are included in the final count.

3. Using Java 8 Streams

If you are using Java 8+, you can utilise streams and Collectors.groupingBy for a more functional approach.

public class StreamCharacterCounter {

    public static Map<Character, Long> countCharacters(String input) {
        return input.chars()
                    .mapToObj(c -> (char) c)
                    .filter(Character::isLetterOrDigit)
                    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    }

    public static void main(String[] args) {
        String str = "Functional Stream!";

        Map<Character, Long> result = countCharacters(str);
        result.forEach((c, count) -> System.out.println(c + ": " + count));
    }
}

The input.chars() method returns an IntStream of character codes from the string, which are then converted back to Character objects using mapToObj(). The groupingBy() collector groups identical characters together, while counting() calculates how many times each character appears, effectively building a frequency map.

Count and Sort by Frequency

You can sort the result by the frequency of each character.

public class SortedFrequencyCounter {

    public static Map<Character, Integer> countAndSort(String input) {
        Map<Character, Integer> countMap = new HashMap<>();

        for (char ch : input.toCharArray()) {
            if (!Character.isLetterOrDigit(ch)) {
                continue;
            }
            countMap.put(ch, countMap.getOrDefault(ch, 0) + 1);
        }

        return countMap.entrySet()
                .stream()
                .sorted(Map.Entry.<Character, Integer>comparingByValue(Comparator.reverseOrder()))
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (a, b) -> a,
                        LinkedHashMap::new));
    }

    public static void main(String[] args) {
        String str = "banana apple orange";

        Map<Character, Integer> sorted = countAndSort(str);
        sorted.forEach((ch, count) -> System.out.println(ch + ": " + count));
    }
}

After counting the character frequencies, the map entries are sorted by their values in descending order using Comparator.reverseOrder(). The sorted entries are then collected into a LinkedHashMap, which maintains the insertion order and ensures that characters appear in the output based on their frequency from highest to lowest.

Sample Output:

a: 5
n: 3
p: 2
e: 2
b: 1
r: 1
g: 1
l: 1
o: 1

4. Using TreeMap for Alphabetical Order

To keep characters sorted alphabetically, use TreeMap instead of HashMap.

public class AlphabeticalFrequencyCounter {

    public static Map<Character, Integer> countAlphabetically(String input) {
        Map<Character, Integer> map = new TreeMap<>();

        for (char ch : input.toCharArray()) {
            if (!Character.isLetter(ch)) {
                continue;
            }
            ch = Character.toLowerCase(ch);
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }

        return map;
    }

    public static void main(String[] args) {
        String input = "TreeMap Alphabetical";

        Map<Character, Integer> result = countAlphabetically(input);
        result.forEach((k, v) -> System.out.println(k + ": " + v));
    }
}

A TreeMap automatically sorts its keys in their natural order, which for characters means alphabetical order. This behaviour is useful when the order of characters is important, such as when displaying results in a structured format.

Sample Output:

a: 4
b: 1
c: 1
e: 3
h: 1
i: 1
l: 2
m: 1
p: 2
r: 1
t: 2

5. Conclusion

In this article, we explored several ways to count the occurrences of each character in a string using Java’s HashMap. Starting with a basic implementation, we then looked at case-insensitive counting, filtering non-letter characters, and more advanced techniques like using Java 8 Streams, sorting results by frequency with LinkedHashMap, and maintaining alphabetical order with TreeMap.

6. Download the Source Code

This article covered how to count character occurrences in Java using HashMap.

Download
You can download the full source code of this example here: java hashmap count occurrences character

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button