Find Common Characters Between Two Strings in Java
Problem
A common character is a letter that appears in both strings being compared, regardless of how many times it appears in either one.
Given two strings, find every character that appears in both.
Java Program
public class CommonCharacters {
public static void main(String[] args) {
String str1 = "apple";
String str2 = "maple";
boolean[] inSecond = new boolean[26];
for (char c : str2.toCharArray()) {
inSecond[c - 'a'] = true; // mark every letter that appears anywhere in str2
}
boolean[] printed = new boolean[26];
StringBuilder result = new StringBuilder();
for (char c : str1.toCharArray()) {
int index = c - 'a';
if (inSecond[index] && !printed[index]) { // in str2, and not already listed
if (result.length() > 0) result.append(", ");
result.append(c);
printed[index] = true; // avoid listing this letter again if it repeats in str1
}
}
System.out.println("Common characters: " + result);
}
}Output
Core Logic
Marking which letters appear anywhere in the second string, then scanning the first string in order, finds every letter both strings share.
- 1A
boolean[26]array namedinSecondmarks which letters appear anywhere instr2. - 2A second
boolean[26]array namedprintedtracks which common letters have already been added to the result, avoiding duplicates. - 3The scan walks
str1in order; a letter is added to the result only if it's marked ininSecondand not yet marked inprinted. - 4Adding a letter to the result also marks it in
printed, so a repeated letter instr1— like the second 'p' in "apple" — isn't listed twice.
"apple" and "maple", the letters 'a', 'p', 'l', and 'e' appear in both, so they're reported in the order they first appear in str1.Key Point: The result order follows str1's first-appearance order, not str2's — swapping which string is scanned would list the same letters in a different order.
Why: Both strings are scanned once each to mark or check letter presence in fixed 26-element arrays, so the extra memory never grows with the input length.
Key Concepts
Approach 2: Java 8
import java.util.Set;
import java.util.stream.Collectors;
public class CommonCharactersStream {
public static void main(String[] args) {
String str1 = "apple";
String str2 = "maple";
Set<Character> secondChars = str2.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.toSet());
// Keeps only str1's distinct characters that also appear in str2's set
String result = str1.chars()
.mapToObj(c -> (char) c)
.distinct()
.filter(secondChars::contains)
.map(String::valueOf)
.collect(Collectors.joining(", "));
System.out.println("Common characters: " + result);
}
}
Output
Core Logic
Building a Set of the second string's characters lets a stream over the first string keep only the ones present in both, in one filtered pass.
- 1
str2.chars().mapToObj(c -> (char) c).collect(Collectors.toSet())builds aSet<Character>of every distinct character instr2. - 2
str1.chars().mapToObj(c -> (char) c).distinct()turnsstr1into a stream of its own distinct characters, in first-appearance order. - 3
.filter(secondChars::contains)keeps only the characters that also appear instr2's set. - 4
.collect(Collectors.joining(", "))joins the surviving characters into the final result.
"apple"'s distinct characters against the set built from "maple" keeps 'a', 'p', 'l', and 'e', matching the manual version.Key Point: .distinct() on str1's stream does the same job as the manual version's printed array — both exist to stop a repeated letter in str1, like the second 'p', from being listed twice.
Why: Both scans still run in time proportional to the input strings, and the set backing the lookups stays bounded by the fixed alphabet size.