Blog Data Structure

🐲 Finding the First Non-Repeating Character in a String with Java 🌟

In this blog post, we’ll explore a common problem in string manipulation: finding the first non-repeating character in a given string. We’ll solve this problem using Java and adhere to clean code principles along the way.

🎯 Problem Statement

Given an input string, we need to find the first character that does not repeat itself in the string. If all characters are repeating, we should throw an exception.

🚀 Initial Solution

Here’s the initial solution provided:

  • Java
  • Python
Java
public class FirstNonRepeatingChar {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String str = reader.readLine();
        int testCases = Integer.parseInt(str);
        while (testCases-->0){
            String input = reader.readLine();
            char result  = getFirstNonRepeatingCharacter(input);
            System.out.println("First Non Repeating Character :" +result);
        }
        reader.close();
    }
    public static Character getFirstNonRepeatingCharacter(String input){
        Map<Character, Integer> hashMap = new LinkedHashMap<>();
        for(int i=0; i<input.length(); i++){
            char ch = input.charAt(i);
            hashMap.put(ch, hashMap.getOrDefault(ch, 0)+1);
        }
        for(Map.Entry<Character, Integer> entry: hashMap.entrySet()){
            if(entry.getValue() == 1){
                return entry.getKey();
            }
        }
        return 0;
    }
}
Python
from collections import OrderedDict

def get_first_non_repeating_character(input_string):
    char_count = OrderedDict()
    for ch in input_string:
        char_count[ch] = char_count.get(ch, 0) + 1
    for ch, count in char_count.items():
        if count == 1:
            return ch
    return None

def main():
    test_cases = int(input())
    while test_cases > 0:
        input_string = input()
        result = get_first_non_repeating_character(input_string)
        if result is not None:
            print("First Non Repeating Character: " + result)
        else:
            print("No non-repeating character found")
        test_cases -= 1

if __name__ == "__main__":
    main()

This solution works by creating a LinkedHashMap that stores each character of the string as a key and its count as a value. The first non-repeating character is then found by iterating over the map and returning the first character with a count of 1. If no such character is found, the method returns 0.

🛠️ Improving the Solution

While the initial solution is correct, it can be improved in two ways:

  1. Exception Handling: Returning 0 when there is no non-repeating character might be confusing because 0 is also a valid character. Instead, we could throw an exception to indicate that there is no such character.
  2. Clean Code Principles: The code can be refactored to adhere to clean code principles. This includes breaking down complex methods into smaller, more manageable methods, using descriptive variable names, and handling exceptions properly.

Here’s the refactored code:

Java
public class FirstNonRepeatingChar {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int testCases = Integer.parseInt(reader.readLine());

        while (testCases-- > 0){
            String input = reader.readLine();
            try {
                char result  = getFirstNonRepeatingCharacter(input);
                System.out.println("First Non Repeating Character :" + result);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }

        reader.close();
    }

    public static char getFirstNonRepeatingCharacter(String input) throws Exception {
        Map<Character, Integer> characterCountMap = createCharacterCountMap(input);
        return getFirstNonRepeatingCharacter(characterCountMap);
    }

    private static Map<Character, Integer> createCharacterCountMap(String input) {
        Map<Character, Integer> characterCountMap = new LinkedHashMap<>();

        for (char character : input.toCharArray()){
            characterCountMap.put(character, characterCountMap.getOrDefault(character, 0) + 1);
        }

        return characterCountMap;
    }

    private static char getFirstNonRepeatingCharacter(Map<Character, Integer> characterCountMap) throws Exception {
        for (Map.Entry<Character, Integer> entry : characterCountMap.entrySet()){
            if (entry.getValue() == 1){
                return entry.getKey();
            }
        }

        throw new Exception("No non-repeating character found");
    }
}

🔄 Method Overloading

In the refactored code, we have two methods with the same name getFirstNonRepeatingCharacter. This is an example of method overloading, a common practice in Java and many other programming languages. It allows us to use the same method name for methods that perform similar tasks, but on different types of input. In this case, both methods are involved in getting the first non-repeating character, but they operate on different types of input (a String and a Map<Character, Integer>).

For more information on method overloading, you can refer to the Java documentation or any good book on Java programming.

🎉 Conclusion

In this blog post, we’ve solved a common string manipulation problem using Java, and along the way, we’ve adhered to clean code principles. Remember, clean code is not just about making the code work, but also about making it work well and ensuring that it’s easy for others (and future you) to understand. Happy coding! 😊

Avatar

Neelabh

About Author

As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

You may also like

Blog Design Pattern

Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
Blog Tech Toolkit

Base64 Decode

Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over