Java 8 - Count Duplicate Characters in a String

Introduction

In this guide, we will explore different ways to count duplicate characters in a string using Java 8 features. Counting duplicate characters is a common task in text processing, and with the introduction of the Stream API in Java 8, there are efficient ways to perform this task.

Problem Statement

Given a string, the task is to count the number of characters that appear more than once in the string.

Example 1:

  • Input: "programming"
  • Output: {'r': 2, 'g': 2, 'm': 2}

Example 2:

  • Input: "java"
  • Output: {'a': 2}

Example 3:

  • Input: "abcd"
  • Output: {} (No duplicates)

Approach 1: Using Collectors.groupingBy and Collectors.counting()

  1. Convert the String to a Stream of Characters: Convert the string to a stream of characters.

  2. Group and Count: Use Collectors.groupingBy to group characters and Collectors.counting to count the occurrences of each character.

  3. Filter Duplicates: Filter the entries to retain only characters with a count greater than 1.

  4. Output the Result: Print the map of duplicate characters with their counts.

Java Program for Approach 1

import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Java 8 - Count Duplicate Characters in a String using Collectors.groupingBy
 * Author: https://www.javaguides.net/
 */
public class DuplicateCharacterCount {

    public static void main(String[] args) {
        String input = "programming";

        // Step 1: Convert the String to a Stream of Characters
        Map<Character, Long> duplicateChars = input.chars()
                .mapToObj(c -> (char) c)  // Convert each int to a char
                // Step 2: Group characters and count occurrences
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
                // Step 3: Filter out characters with only one occurrence
                .entrySet().stream()
                .filter(entry -> entry.getValue() > 1)
                // Step 4: Collect the results into a Map
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        // Step 5: Output the result
        System.out.println("Duplicate Characters: " + duplicateChars);
    }
}

Output for Approach 1

For the input string "programming", the output will be:

Duplicate Characters: {r=2, g=2, m=2}

Approach 2: Using Stream with Map and merge Function

  1. Create a Map: Initialize a map to keep track of character counts.

  2. Iterate and Merge: Convert the string to a stream of characters, then iterate over the stream and merge counts into the map.

  3. Filter Duplicates: Retain only characters with a count greater than 1.

  4. Output the Result: Print the map of duplicate characters with their counts.

Java Program for Approach 2

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Java 8 - Count Duplicate Characters in a String using Stream and Map.merge
 * Author: https://www.javaguides.net/
 */
public class DuplicateCharacterCountWithMerge {

    public static void main(String[] args) {
        String input = "java";

        // Step 1: Create a Map to store character counts
        Map<Character, Integer> characterCountMap = new HashMap<>();

        // Step 2: Iterate over the string and update the counts in the Map
        input.chars()
                .mapToObj(c -> (char) c)  // Convert each int to a char
                .forEach(ch -> characterCountMap.merge(ch, 1, Integer::sum)); // Merge counts

        // Step 3: Filter out characters with only one occurrence
        Map<Character, Integer> duplicateChars = characterCountMap.entrySet().stream()
                .filter(entry -> entry.getValue() > 1)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        // Step 4: Output the result
        System.out.println("Duplicate Characters: " + duplicateChars);
    }
}

Output for Approach 2

For the input string "java", the output will be:

Duplicate Characters: {a=2}

Approach 3: Using Collectors.toMap with BinaryOperator

  1. Convert the String to a Stream of Characters: Convert the string to a stream of characters.

  2. Collect to a Map: Use Collectors.toMap to collect characters into a map, where the key is the character and the value is the count.

  3. Handle Duplicates: Use a BinaryOperator to handle the case where a character is already in the map.

  4. Filter and Output: Filter the map to retain only duplicate characters and print the result.

Java Program for Approach 3

import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Java 8 - Count Duplicate Characters in a String using Collectors.toMap
 * Author: https://www.javaguides.net/
 */
public class DuplicateCharacterCountWithToMap {

    public static void main(String[] args) {
        String input = "abcdabc";

        // Step 1: Convert the String to a Stream of Characters and collect to a Map
        Map<Character, Integer> duplicateChars = input.chars()
                .mapToObj(c -> (char) c)  // Convert each int to a char
                .collect(Collectors.toMap(
                        Function.identity(),  // The key is the character
                        c -> 1,  // The initial count is 1
                        Integer::sum  // Merge counts by summing them up
                ));

        // Step 2: Filter out characters with only one occurrence
        Map<Character, Integer> filteredDuplicateChars = duplicateChars.entrySet().stream()
                .filter(entry -> entry.getValue() > 1)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        // Step 3: Output the result
        System.out.println("Duplicate Characters: " + filteredDuplicateChars);
    }
}

Output for Approach 3

For the input string "abcdabc", the output will be:

Duplicate Characters: {a=2, b=2, c=2}

Conclusion

These Java 8 approaches demonstrate different ways to count duplicate characters in a string using streams and modern Java features. Each approach is effective, but the choice of method may depend on specific use cases, such as ease of readability, performance, or specific API features that need to be leveraged. By mastering these techniques, you can efficiently handle string processing tasks in Java.

Related Java 8 Programs

Comments