Show the amount of each letter of the alphabet in a String

I am doing an exercise in Java where the user enters with a sentence. After that, I have to list how many letters there are in the sentence, for example:

Entry = Daniel Henrique
Output:

A = 1 B = 0 C = 0 D = 1 ... Z = 0

Follows Code:

String frase = "";
int n = 0;
int c = 97;
int letra = 0;
int qtdn = 0;

System.out.print("Frase: ");
frase = leia.nextLine();

for (int i = 0; i < frase.length(); i++) {
    while (c <= 122) {
        if (frase.toLowerCase().charAt(i) == (char) c) {
            qtdn++;
        }
        System.out.println((char) c + " = " + qtdn);
        c++;
    }

}
Author: Maniero, 2019-11-18

3 answers

I decided to answer because I did not like the current solutions, although certain. In general, the staff does not Program thinking about performance. In such an algorithm that can be used repeatedly can cause great damage and then the staff blames Java for consuming too much memory. In one solution (a currently accepts) it makes an allocation of string without need, and in the other (the most voted currently) it makes two allocations, which generates pressure on the garbage collector , so I I catch each character locally and manipulate it, eliminating unnecessary allocations. It may seem that it has more processing, but you will look at what is inside these used functions, you are using up to 3 loops without even realizing it:

class Main {
    public static void main (String[] args) {
        String frase = "Daniel Henrique";
        int[] quantidades = new int[26];
        for (int i = 0; i < frase.length(); i++) {
            if (frase.charAt(i) > 64 && frase.charAt(i) < 91) quantidades[frase.charAt(i) - 65]++;
            if (frase.charAt(i) > 96 && frase.charAt(i) < 123) quantidades[frase.charAt(i) - 97]++;
        }
        for (int i = 0; i < quantidades.length; i++) System.out.println((char)(i + 65) + " => " + quantidades[i]);
    }
}

See working on ideone. E no repl.it. also I put on GitHub for future reference .

 2
Author: Maniero, 2019-11-20 13:21:37

What you can do is reverse the order of the loops, i.e. for each letter of the alphabet you count in the sentence how many there are, see the example below:

        String frase = "Daniel Henrique";
        int n = 0;
        int c = 97;
        int letra = 0;

        System.out.print("Frase: ");
        frase = leia.nextLine();

        while (c <= 122) {
            int qtdn = 0;
            for (int i = 0; i < frase.length(); i++) {
                if (frase.toLowerCase().charAt(i) == (char) c) {
                    qtdn++;
                }
            }
            System.out.println((char) c + " = " + qtdn);
            c++;

        }

    }
 3
Author: Marciano Machado, 2019-11-18 18:45:17

You don't have to do a loop inside another, as this is pretty inefficient: for each character of String, you want to compare it with each of the 26 letters, so at the end you'll be doing N * 26 iterations (being N the size of String).

You can do all this by going through String once. Just create an array containing the count of each letter, and update it as you go through String.

Then you make another loop to show the quantities of each letter:

String frase = "Daniel Henrique";
int[] quantidades = new int[26];

for (char c : frase.toUpperCase().toCharArray()) {
    int indice = c - 65;
    if (indice >= 0 && indice < 26) {
        quantidades[indice] += 1;
    }
}

for (int i = 0; i < quantidades.length; i++) {
    char letra = (char) (i + 65);
    System.out.println(letra + "=" + quantidades[i]);
}

First I create an array containing the quantities of each letter, so it has 26 positions. I take advantage of the fact that in Java, an array of int Created in this way is already initialized with zero in all positions (which is precisely what we need, since at the beginning the amount of any letter is zero, since I have not yet started counting).

In the first for I run through String. In your code gave to understand whether the letters are uppercase or lowercase, then I'm using uppercase (toUpperCase()).

For each character, I check if it is a letter from A to Z (by subtracting 65 from a char, if this is a letter from A to Z, the result will be between zero and 25, which is a valid position in the quantity array). If it is, I sum 1 in the respective amount.

In the second for I print the letters and their respective quantities. In the end, I just walked the String and the quantities once, totaling N + 26 iterations (being N the size of String) - much better than making a loop inside another, which as already said, generates N * 26 iterations.

 3
Author: hkotsubo, 2019-11-18 19:02:00