1. Overview
In this tutorial, we will learn to check, if a given string is valid pangram or not using a simple Java program. A pangram is any string that contains all letters of a given alphabet set at least once.
2. Pangrams
Pangrams are applicable to not only English language, but also to any other language having a fixed character set.
For example, a commonly known English pangram is “A quick brown fox jumps over the lazy dog”. Similarly, these are available in other languages, too.
3. Using a for Loop
First, let’s try a for loop. We’ll populate a Boolean array with markers for each character of the alphabet.
The code returns true when all the values in the marker array are set to true:
public static boolean isPangram(String str) { if (str == null) { return false; } Boolean[] alphabetMarker = new Boolean[ALPHABET_COUNT]; Arrays.fill(alphabetMarker, false); int alphabetIndex = 0; str = str.toUpperCase(); for (int i = 0; i < str.length(); i++) { if ('A' <= str.charAt(i) && str.charAt(i) <= 'Z') { alphabetIndex = str.charAt(i) - 'A'; alphabetMarker[alphabetIndex] = true; } } for (boolean index : alphabetMarker) { if (!index) { return false; } } return true; }
Let’s test our implementation:
@Test public void givenValidString_isPanagram_shouldReturnSuccess() { String input = "Two driven jocks help fax my big quiz"; assertTrue(Pangram.isPangram(input)); }
4. Using Java Streams
An alternate approach involves using the Java Streams API. We can create a filtered character stream out of the given input text and create an alphabet Map using the stream.
The code returns success if the size of the Map is equal to the size of the alphabet. For English, the expected size is 26:
public static boolean isPangramWithStreams(String str) { if (str == null) { return false; } String strUpper = str.toUpperCase(); Stream<Character> filteredCharStream = strUpper.chars() .filter(item -> ((item >= 'A' && item <= 'Z'))) .mapToObj(c -> (char) c); Map<Character, Boolean> alphabetMap = filteredCharStream.collect(Collectors.toMap(item -> item, k -> Boolean.TRUE, (p1, p2) -> p1)); return alphabetMap.size() == ALPHABET_COUNT; }
And, of course, let’s test:
@Test public void givenValidString_isPangramWithStreams_shouldReturnSuccess() { String input = "The quick brown fox jumps over the lazy dog"; assertTrue(Pangram.isPangramWithStreams(input)); }
5. Modifying for Perfect Pangrams
A perfect pangram is a little bit different than a regular pangram. A perfect pangram consists of each letter of the alphabet exactly once as opposed to at least once for a pangram.
The code returns true when both the Map size equals the alphabet size and the frequency of each character in the alphabet is exactly one:
public static boolean isPerfectPangram(String str) { if (str == null) { return false; } String strUpper = str.toUpperCase(); Stream<Character> filteredCharStream = strUpper.chars() .filter(item -> ((item >= 'A' && item <= 'Z'))) .mapToObj(c -> (char) c); Map<Character, Long> alphabetFrequencyMap = filteredCharStream.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); return alphabetFrequencyMap.size() == ALPHABET_COUNT && alphabetFrequencyMap.values().stream().allMatch(item -> item == 1); }
And let’s test:
@Test public void givenPerfectPangramString_isPerfectPangram_shouldReturnSuccess() { String input = "abcdefghijklmNoPqrStuVwxyz"; assertTrue(Pangram.isPerfectPangram(input)); }
A perfect pangram should have each character exactly once. So, our previous pangram should fail:
String input = "Two driven jocks help fax my big quiz"; assertFalse(Pangram.isPerfectPangram(input));
In the above code, the given string input has several duplicates, like it has two o’s. Hence the output is false.
5. Conclusion
In this article, we’ve covered various solution approaches to find out whether a given string is a valid pangram or not.
We also discussed one other flavor of pangrams which is called perfect pangram & how to identify it programmatically.
The code sample is available over on GitHub.