HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Print total occurrences of a char in a string

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
totaloccurrencescharprintstring

Problem

Scenario: Count the total number of times a char occurs in a word.

For instance, "aaabbcccdddaaaa" should print out "a7b2c3d3".

Can you please critique my code?

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

public class Demo {

    public static void main(final String[] args) {
        final Demo d = new Demo();
        final String name = "aaabbcccdddaaaa";
        System.out.println(d.countNoOfInteger(name));
    }

    public String countNoOfInteger(final String str) {
        if (str.equals(null)) {
            throw new IllegalArgumentException();
        }
        if (str.isEmpty()) {
            return "";
        }

        final Map map = new HashMap<>();
        int count = 0;
        final char[] charArray = str.trim().toCharArray();

        for (final char element : charArray) {
            if (map.get(element) != null) {
                count = map.get(element);
                map.put(element, ++count);
            } else {
                count = 0;
                map.put(element, ++count);
            }
        }

        int total;
        char ch;
        final Map visited = new HashMap<>();
        final StringBuilder sb = new StringBuilder();
        for (final char element : charArray) {
            if ((visited.get(element) == null)) {
                ch = element;
                sb.append(ch);
                total = map.get(element);
                sb.append(total);
                visited.put(element, true);
            }
        }
        return sb.toString();
    }
}

Solution

The use of Map is unnecessary overhead. You can leverage the fact that chars can be mapped as ints along with a simple array to solve this problem.

private static final int OFFSET = 'a';

public String countNoOfInteger(final String str) {
    final int[] counts = new int[26];  // or 'z' - 'a' + 1, if you prefer
    for (final char character : str.toCharArray()) {
        counts[character - OFFSET]++;
    }

    final StringBuilder output = new StringBuilder();
    for (int i = 0; i < counts.length; i++) {
        if (counts[i] == 0) {
            continue;
        }
        output.append((char) (i + OFFSET));
        output.append(counts[i]);
    }

    return output.toString();
}


Some notes:

  • OFFSET could probably have a better name. I'll leave that as an exercise for the reader.



  • Contrary to other respondents, I heartily encourage the use of final as a statement of intent.



  • In a "real" system, it would be preferable to separate the business logic (find the letter counts) from the display logic (print them to the screen). In such a system, your method would return the counts int[] (or Map) and the caller (main(), in this case) would be responsible for displaying it (everything after the first for loop).



  • Note that this solution will fail spectacularly for invalid input. If that's something you need to handle, add a check to the first loop to ensure that character is between offset and offset + counts.length.

Code Snippets

private static final int OFFSET = 'a';

public String countNoOfInteger(final String str) {
    final int[] counts = new int[26];  // or 'z' - 'a' + 1, if you prefer
    for (final char character : str.toCharArray()) {
        counts[character - OFFSET]++;
    }

    final StringBuilder output = new StringBuilder();
    for (int i = 0; i < counts.length; i++) {
        if (counts[i] == 0) {
            continue;
        }
        output.append((char) (i + OFFSET));
        output.append(counts[i]);
    }

    return output.toString();
}

Context

StackExchange Code Review Q#116436, answer score: 3

Revisions (0)

No revisions yet.