简体   繁体   中英

JAVA - store letters and number of letters in string

I am supposed to ask the user to enter a string and I am supposed to parse the string and keep track of the number of the alphabet. So like if the user enter the string "abee" it displays the output as :

a: 1
b: 1
c: 0
e: 2

So far I have been able to get the string and parse it and store the elements into an array. And I have been able to print out each letter at a time with a for loop. Now the problem I am facing is that when it prints out the letters along with how many of the letters exist in the phrase the numbers don't match up. For example if I enter the letters : "abccddee" it prints out:

a: 1
b: 1
c: 1
c: 0
d: 0
d: 0
e: 0
e: 0

For testing purposes I am using my own string rather than using the scanner.

import java.util.Scanner;

public class CountLetters
{

    public static void main(String[] args)
    {

        //create arrays
        String[] upper = new String[25];
        String[] lowerChar = new String[25];
        int [] lowerCharNum = new int[25];

        Scanner input = new Scanner(System.in);

        System.out.println("Please enter a phrase");

        //grab phrase from user
        String phrase = "abccddee";

        //create array with the size of the phrase entered from user
        String[] letters = new String[phrase.length()];
        System.out.println("letters length: " + letters.length);

        //separate every letter in phrase and store it into array "letters"
        letters = phrase.split("");

        for(int i=0; i<letters.length; i++)
        {
            lowerChar[i] = letters[i];
             switch(letters[i])
             {
               case "a":
                   lowerCharNum[0] += 1;
                   break;
               case "b":
                   lowerCharNum[1] += 1;
                   break;
               case "c":
                   lowerCharNum[2] += 1;
                   break;
               case "d":
                   lowerCharNum[3] += 1;
                   break;
               case "e":
                   lowerCharNum[4] += 1;
                   break;
               case "f":
                   lowerCharNum[5] += 1;
                   break;
            }//end of switch
            System.out.println(lowerChar[i] + ": " + lowerCharNum[i]);
        }
    }//end of main method
}//end of class

Rather than working with simple array you can work with java's Collection 's HashMap .

With HashMap the main working goes around with the for loop, will check if the Character is already present in the HashMap if it is then we will get the value associated with Character and will add 1 with the existing value and if the Character is not present then we will put a Character in HashMap and will store the initial count 1 with the associated character.

        HashMap<Character, Integer> lettersCount = new HashMap<>();
        String phrase = "abccddee";
        int length = phrase.length();
        int count = 1;
        for (int i = 0; i < length; i++) {
        int integer = 0;
        char charAt = input.charAt(i);
        if (!lettersCount.containsKey(charAt)) {
            lettersCount.put(charAt, 0);
        }
        integer = lettersCount.get(charAt);
        integer = initialCount + integer;
        lettersCount.put(charAt, integer);
    }
    System.out.println(lettersCount);

You are using array which you will be needed to intialize first at time of declaration this will create a extra memory space which will be waste if all 26 letters are not being encountered and as per the code you have provided in the question you are allocating 3 arrays so it will take much more memory, So rather this solution will require only a HashMap ( HashMap will allocate memory according to the key and value inserted in HashMap )and a for loop which will just compute the occurence of Charater and to use it again further in your program will be much more easier with it.

You are printing within the for loop. You should print the frequency outside that loop.

The method which you are using is not scalable. You will have to write 52 case statements in your switch given that the phrase consists only of uppercase and lowercase English alphabets.

A better way to do the same would be to use the ASCII encoding for your purpose. You can have something on the following lines:

int frequency[] = new int[128];
for (int i = 0; i < phrase.length(); i++) {
    frequency[(int) phrase.charAt(i)]++;
}

In this method frequency array is used to count the occurrences of first 128 ASCII characters in phrase string. Operation (int) phrase.charAt(i) simply converts the character into corresponding ASCII code and we increase the counter for that character by 1. At the end of the processing, frequency array will contain the number of occurrences of first 128 ASCII characters in the given phrase string. Simply print this frequency to achieve desired output.

print statement must be outside the while for loop.

System.out.println(lowerChar[i] + ": " + lowerCharNum[i]);

updated: you need to parse entire string first, then start printing.

import java.io.*;
import java.util.*;
 class CountLetters {

    public static void main(String[] args)
    {
int i;
          //create arrays
        String[] upper = new String[25];
        String[] lowerChar = new String[25];
        int [] lowerCharNum = new int[25];


        Scanner input = new Scanner(System.in);

        System.out.println("Please enter a phrase");

        //grab phrase from user
        String phrase = "abccddee";

        //create array with the size of the phrase entered from user
        String[] letters = new String[phrase.length()];
        System.out.println("letters length: " + letters.length);

        //seperate every letter in phrase and store it into array "letters"
        letters = phrase.split("");


        for(i=0; i<letters.length; i++)
        {
            lowerChar[i] = letters[i];
        switch(letters[i])
         {
         case "a":
            lowerCharNum[0] += 1;
             break;
         case "b":
            lowerCharNum[1] += 1;
             break;
         case "c":
            lowerCharNum[2] += 1;
             break;
         case "d":
            lowerCharNum[3] += 1;
             break;
         case "e":
            lowerCharNum[4] += 1;
             break;
         case "f":
            lowerCharNum[5] += 1;
             break;
         }//end of switch



        }

for(i=0;i<5;i++)
System.out.println(lowerChar[i] + ": " + lowerCharNum[i]);



    }//end of main method


}//end of class

Your solution with arrays is a bit complicated. By using a Map instead we can directly associate the encountered characters with the number of times they have been encountered, thus making it very straight-forward to increase the counter and to output the counter without having to look up indices in different arrays.

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

public class CountLetters
{

    public static void main(String[] args)
    {

        Scanner input = new Scanner(System.in);

        System.out.println("Please enter a phrase");

        //grab phrase from user
        String phrase = "abccddee";

        //create array with the phrase entered from user
        char[] letters = phrase.toCharArray();
        System.out.println("letters length: " + letters.length);

        // Map to keep track of all encountered characters and the
        // number of times we've encountered them
        Map<Character, Integer> characterCounts = new HashMap<>();
        for(int i=0; i<letters.length; i++)
        {
            Character character = letters[i];
            if(characterCounts.containsKey(character))
            {
                // We've encountered this character before, increase the counter
                characterCounts.put(character, characterCounts.get(character) + 1);
            }
            else
            {
                // This is the first time we encounter this character
                characterCounts.put(lowerChar, 1);
            }
        }

        // Iterate over all character-counter pairs and print them
        for(Map.Entry<Character, Integer> entry : characterCounts.entrySet())
        {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }//end of main method
}//end of class
  • HashMap - Stores keys and values in an unordered way and contains only unique keys.
  • TreeMap - Stores keys and values in a naturally ordered way and contains only unique keys.
  • LinkedHashMap - Stores keys and values in the order of keys insertions and contains only unique keys.

The appropriate data structure for such requirement will be a Map . If you want to maintain the order of letters in which they appeared in the String, you can use LinkedHashMap, if the order of letters in not a concern then you can you a HashMap. I am using LinkedHashMap for my example.

public class Test {

    public static void main(String[] args) {

        //Taking the input from the user
        System.out.println("Enter the String"); //I am entering "abccddee" for your example
        Scanner sc = new Scanner(System.in);
        String input = sc.next(); 

        //LinkedhashMap preserves the order in which input was supplied
        LinkedHashMap<Character, Integer> lhm = new LinkedHashMap<Character, Integer>();

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

            //method get will return null if the letter is not available at the given index else it will return the count
            Integer j = lhm.get(input.charAt(i));

            //If the chracter was not present in the String
            if(j==null)
                lhm.put(input.charAt(i),1);
            //If the character was present in the String
             else
                lhm.put(input.charAt(i),j+1);

         }

         for(Character c : lhm.keySet())  
             System.out.println(c+": "+lhm.get(c)+" ");

    }

}

The output will be:

a: 1 
b: 1 
c: 2 
d: 2 
e: 2 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM