Today I present to you a program that:

  • Identifies vowels and their total number
  • Prints each vowel's numeric value
  • Adds the numeric value of each vowel found
  • Prints which letters are NOT vowels

If you want to check out the rules from where I got the project, here you go.

package countVowels;

import java.util.Scanner;

public class vowelCounter {

static Scanner scan = new Scanner(System.in);
static String word;

char vowel;

int valueOfVowel;
int totalValueOfVowels = 0;
int iterations = 0;
int i;



public void counter() {


    for(i = 0; i < word.length();) {
        vowel = word.charAt(i);

            if (vowel == 'a' || vowel == 'e' || vowel == 'i' || vowel == 'o' || vowel == 'u') {
                valueOfVowel = Character.getNumericValue(vowel);

                iterations++;
                totalValueOfVowels += valueOfVowel;
                i++;

                System.out.println("The vowel is: " + vowel + "  ");
                System.out.println("Character value of " + vowel + ": " + valueOfVowel);
                System.out.println("------------------------");

            }else {
                System.out.println("This isn't a vowel: " + word.charAt(i));
                System.out.println("------------------------");
                i++;
            }
        }   

      while(i == word.length()) {  

          System.out.println("The number of vowels is: " + iterations);
          System.out.println("The total sum of all vowels is: " + totalValueOfVowels);
          break;

        }
}


public static void main(String[] args) {
    word = scan.next();
    scan.close();
    new vowelCounter().counter();

    }
}
up vote 7 down vote accepted

Use consistent code formatting

Right now, you have several lines of code with different indentations, spacing, etc. You should pick a single spacing style and stick with it for the entirety of your program to improve readability.

while(i == word.length()) {  

    System.out.println("The number of vowels is: " + iterations);
    System.out.println("The total sum of all vowels is: " + totalValueOfVowels);
    break;

  }

Here, for example, your closing curly brace does not line up with the beginning of the while loop. Similarly,

}else {
    System.out.println("This isn't a vowel: " + word.charAt(i));
    System.out.println("------------------------");

Your else statement has a space after it, but not before.

It generally doesn't matter what coding style you choose, as long as you do choose one and stick with it.


Initialize variables at the first point of use

Variables should be initialized as closely to where they are used as possible. For example, your scan variable is only used in your main method, so it should be initialized there.

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    ...
}

Do the same for the rest of your variables. All the rest of them (except for word) are only used in the counter method, so they should be initialized there, as close to their first point of use as possible.

word is initialized in main and then used in counter, so it should be passed in to counter as an argument.

public static void counter(String word) {
    ....
}

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    String word = scan.next();
    scan.close();
    counter(word);
}

As you can see, we can pass word as an argument to counter.


Simplify your call to counter

The above snippet also addresses another issue - the counter method is only called from main, which means you can make it a static method. This way, we do not have to initialize a new vowelCounter just to call the counter method - we can freely call it from main.

If you really wanted to make counter a non-static method, then I would suggest moving it to a different class than your main method. Then, you can create an instance of that class and call the counter method on it. In general, creating a new instance of the class that contains your main method is a strange pattern and should be avoided.


Simplify your for-loop

In general, a variable used as a counter in a for-loop should be initialized and incremented within that for-loop statement itself. To accomplish this, you would want to remove the int i and the lines that call i++;, and format your for-loop as follows:

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

However, there is an even better way to express our intent of "loop over all characters in a String". We can format our for-loop into a foreach-loop as follows:

for (char vowel : word) {
    ...
}

Now, we can remove the line vowel = word.charAt(i), since vowel will now automatically loop over every character in the given word.

  • 3
    I would also suggest to remove the while(i == word.length()) check. It's useless as the for-loop exits at this very condition. – Markus Mitterauer Aug 16 at 21:39

Make sure to format your code properly, indenting the code inside code blocks.

Class names in Java have names in CamelCase per the coding style guide.

public class VowelCounter {

It's a good idea to add javadoc to your methods to explain their purpose

/**
     * Count occurrence of each vowel in the input string
     * @param word - the string to process
     * @return a map with each vowel and their respective counts
     */

It's a good idea to have your method return the result so that it can be checked/unit tested at the caller.

    public Map<Character, Long> getCount(String word) {

Here's a different way to achieve what you need. I have checked the original link of the task and it's my understanding that you're supposed to print out the count of each vowel, not their sums.

    Set<Character> validVowels = Set.of('a', 'e', 'i', 'o', 'u');

        Map<Character, Long> vowelCountMap = new HashMap<>();
        // Initialize the map with the valid vowels and a count of zero
        // This way we have a valid count for all valid vowels
        for (Character vowel : validVowels) {
            vowelCountMap.put(vowel, 0L);
        }

        // Ensure equal handling of UPPERCASE and lowercase characters
        String wordInLowerCase = word.toLowerCase();

        for (int i = 0; i < wordInLowerCase.length(); i++) {
            var character = wordInLowerCase.charAt(i);

            // valid vowels contains all vowels 'a', 'e', 'i', 'o', 'u'. 
            // If the current character is a vowel, then valid vowels will contain it
            if (validVowels.contains(character)) {
                Long count = vowelCountMap.get(character);
                // No need to handle null count since it's been initialized above
                count++;
                vowelCountMap.put(character, count);
            }
        }

        return vowelCountMap;
    }

I know you used the Scanner for the purposes of your test, though there are many approaches to this, I'm suggesting yet another one, where I'm setting a few test cases and throwing them at the method to check that it works on all edge cases, including empty string. It's important to test all the possible cases to ensure program accuracy.

    public static void main(String[] args) {
        String threeAs = "blablabla";
        printOccurrences(threeAs);
        String mixedCase = "BLAbleBLIbloBLU";
        printOccurrences(mixedCase);
        String twoOfEachVowel = "aaeeiioouu";
        printOccurrences(twoOfEachVowel);
        String emptyString = "";
        printOccurrences(emptyString);
        String noVowels = "bcdfg";
        printOccurrences(noVowels);
    }

    private static void printOccurrences(String word) {
        System.out.println("Processing word: " + word);
        System.out.println("-------------------------------------------------------");
        Map<Character, Long> vowelCountMap = new VowelCounter().getCount(word);
        for (Character vowel : vowelCountMap.keySet()) {
            Long count = vowelCountMap.get(vowel);
            System.out.println(String.format("Vowel: %s has %d occurrences", vowel, count));
        }
        System.out.println(".......................................................");
    }
}

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.