Java Strings Tutorial: String, StringBuilder, Regex & Best Practices (2026)
⏱️ Reading Time: 28 minutes | 🎯 Difficulty: Beginner | 🔄 Last Updated: August 21, 2026
What is a String in Java?
A String in Java is a sequence of characters. Unlike primitive types like int or double, String is a class from the java.lang package — meaning it is an object with methods, properties, and behavior.
1String language = "Java"; 2String greeting = "Hello, World!"; 3String number = "12345"; // Still a String, not an int!
Every string you create is internally stored as an array of characters (char[] or byte[] in modern Java), wrapped in the String class with powerful methods for manipulation, searching, and transformation.
Why Are Strings So Important?
"I once built an API that processed 10,000 user inputs per second. I used String concatenation in a loop. The server crashed within minutes. Understanding String vs StringBuilder saved my job." — Backend developer, production incident report.
Text is the universal language of software. Every application processes strings:
| Domain | String Operations |
|---|---|
| Web Development | HTML generation, URL parsing, JSON handling |
| Mobile Apps | User input, notifications, search queries |
| Data Science | CSV parsing, text cleaning, tokenization |
| Cybersecurity | Password validation, sanitization, encryption |
| E-commerce | Product names, descriptions, search filters |
| Banking | Account numbers, transaction references, IFSC codes |
In Java, strings are used so frequently that the language provides special treatment — String literals, the String Pool, and compiler optimizations all exist to make string handling efficient.
Creating Strings in Java
There are two primary ways to create strings in Java:
Method 1: String Literal (Recommended)
1String language = "Java";
When you use a literal, Java checks the String Pool first. If the string already exists, it reuses the existing object. This saves memory.
Method 2: Using the new Keyword
1String language = new String("Java");
This always creates a new object in the heap memory, even if an identical string already exists in the pool.
Visual Comparison
String a = "Java"; // Points to String Pool
String b = "Java"; // Points to SAME object in pool
String c = new String("Java"); // New object in Heap
String d = new String("Java"); // ANOTHER new object in Heap
String Pool Heap
+--------+ +--------+
| "Java" | | "Java" | ← c
+--------+ +--------+
↑ ↑ +--------+
a b | "Java" | ← d
+--------+
Example: Proving the Difference
1public class StringCreation { 2 public static void main(String[] args) { 3 String a = "Java"; 4 String b = "Java"; 5 String c = new String("Java"); 6 String d = new String("Java"); 7 8 System.out.println("a == b: " + (a == b)); // true (same pool object) 9 System.out.println("c == d: " + (c == d)); // false (different heap objects) 10 System.out.println("a == c: " + (a == c)); // false (pool vs heap) 11 12 System.out.println("a.equals(c): " + a.equals(c)); // true (same content) 13 } 14}
Output:
1a == b: true 2c == d: false 3a == c: false 4a.equals(c): true
Golden Rule: Use string literals (
"text") unless you have a specific reason to usenew String().
The String Pool
The String Pool (also called the String Intern Pool) is a special area inside the Java Heap that stores unique string literals. It acts like a cache for strings.
How It Works
- You write:
String s = "Hello"; - JVM checks the pool: Is
"Hello"already there? - Yes → Reuse the existing object.
spoints to it. - No → Create
"Hello"in the pool.spoints to it.
Manual Interning
You can force a heap string into the pool using .intern():
1String heap = new String("Java"); 2String pooled = heap.intern(); // Moves to pool (or returns existing) 3 4String literal = "Java"; 5System.out.println(pooled == literal); // true!
Why the Pool Matters
| Without Pool | With Pool |
|---|---|
10,000 "Java" strings = 10,000 objects | 10,000 references = 1 object |
| Massive memory waste | Huge memory savings |
| Slower garbage collection | Faster GC |
String Immutability
In Java, Strings are immutable — once created, their content cannot be changed. Any operation that appears to modify a string actually creates a new string object.
What Immutability Looks Like
1String text = "Java"; 2text = text + " Programming"; // Creates NEW object! 3 4// Original "Java" still exists in memory (until GC) 5// text now points to "Java Programming"
Visual Proof
Step 1: String text = "Java";
text
↓
"Java" (in pool)
Step 2: text = text + " Programming";
text
↓
"Java Programming" (new object)
"Java" (still in pool, unmodified)
Advantages of Immutability
| Advantage | Explanation |
|---|---|
| Thread Safety | Multiple threads can share a string without synchronization |
| Security | Passwords and keys cannot be modified after creation |
| Hash Caching | hashCode() is computed once and cached — fast HashMap keys |
| String Pool | Safe to reuse references because content never changes |
The Concatenation Trap
1// DANGEROUS — Creates 1000 intermediate string objects! 2String result = ""; 3for (int i = 0; i < 1000; i++) { 4 result = result + i; // Creates new String EVERY iteration! 5} 6 7// 1000 objects created → Massive GC pressure → Slow performance
⚠️ Critical: Never concatenate strings in a loop using
+. UseStringBuilderinstead.
StringBuilder
StringBuilder is a mutable sequence of characters. Unlike String, modifying a StringBuilder does not create new objects — it changes the existing buffer.
When to Use StringBuilder
- Concatenating strings in loops
- Building dynamic SQL queries
- Generating HTML/XML content
- Processing large text files
- Any scenario with frequent string modifications
Syntax
1StringBuilder sb = new StringBuilder(); 2// or 3StringBuilder sb = new StringBuilder("Initial text");
Example: Efficient Concatenation
1public class StringBuilderDemo { 2 public static void main(String[] args) { 3 StringBuilder sb = new StringBuilder(); 4 5 sb.append("Java"); 6 sb.append(" Programming"); 7 sb.append(" Language"); 8 9 String result = sb.toString(); 10 System.out.println(result); // Java Programming Language 11 } 12}
Common StringBuilder Methods
| Method | Description | Example |
|---|---|---|
append(str) | Adds text at the end | sb.append("!"); |
insert(index, str) | Inserts text at position | sb.insert(5, "Great "); |
replace(start, end, str) | Replaces a range | sb.replace(0, 4, "Python"); |
delete(start, end) | Deletes a range | sb.delete(5, 10); |
reverse() | Reverses the sequence | sb.reverse(); |
length() | Returns character count | sb.length(); |
capacity() | Returns current buffer size | sb.capacity(); |
charAt(index) | Character at position | sb.charAt(0); |
toString() | Converts to String | sb.toString(); |
Method Chaining
StringBuilder methods return the same object, allowing elegant chaining:
1String result = new StringBuilder() 2 .append("Hello") 3 .append(" ") 4 .append("World") 5 .append("!") 6 .toString(); 7 8System.out.println(result); // Hello World!
StringBuffer
StringBuffer is nearly identical to StringBuilder but with one critical difference: all its methods are synchronized, making it thread-safe.
When to Use StringBuffer
- Multi-threaded environments where multiple threads modify the same string
- Legacy codebases that require synchronization
- When thread safety is more important than speed
Example
1public class StringBufferDemo { 2 public static void main(String[] args) { 3 StringBuffer buffer = new StringBuffer("Hello"); 4 buffer.append(" Java"); 5 buffer.append(" World"); 6 System.out.println(buffer); // Hello Java World 7 } 8}
String vs StringBuilder vs StringBuffer
| Feature | String | StringBuilder | StringBuffer |
|---|---|---|---|
| Mutable? | ❌ Immutable | ✅ Mutable | ✅ Mutable |
| Thread-safe? | ✅ Yes (immutable) | ❌ No | ✅ Yes (synchronized) |
| Performance | Fast for reading | 🚀 Fastest for single-threaded writes | Slower (synchronization overhead) |
| Use case | Constants, keys, labels | Loop concatenation, single-threaded building | Shared string building across threads |
| Memory | Creates new objects per change | Reuses buffer | Reuses buffer |
Decision Tree
Do you need to modify the text after creation?
├── NO → Use String
└── YES → Multiple threads will access it?
├── YES → Use StringBuffer
└── NO → Use StringBuilder (preferred)
Common String Methods
Java's String class provides over 50 methods. Here are the most essential ones:
length() — Character Count
1String text = "Java Programming"; 2System.out.println(text.length()); // 16
charAt(index) — Character at Position
1String text = "Java"; 2System.out.println(text.charAt(0)); // J 3System.out.println(text.charAt(2)); // v
toUpperCase() / toLowerCase()
1String text = "Java"; 2System.out.println(text.toUpperCase()); // JAVA 3System.out.println(text.toLowerCase()); // java
substring(begin) / substring(begin, end)
1String text = "Programming"; 2System.out.println(text.substring(3)); // gramming (from index 3 to end) 3System.out.println(text.substring(3, 7)); // gram (index 3 to 6)
contains(CharSequence)
1String text = "Java Programming"; 2System.out.println(text.contains("gram")); // true 3System.out.println(text.contains("Python")); // false
startsWith() / endsWith()
1String file = "document.pdf"; 2System.out.println(file.startsWith("doc")); // true 3System.out.println(file.endsWith(".pdf")); // true
indexOf() / lastIndexOf()
1String text = "banana"; 2System.out.println(text.indexOf('a')); // 1 (first occurrence) 3System.out.println(text.lastIndexOf('a')); // 5 (last occurrence) 4System.out.println(text.indexOf("na")); // 2
replace() / replaceAll()
1String text = "I love Java"; 2System.out.println(text.replace("Java", "Python")); // I love Python 3System.out.println(text.replaceAll("[aeiou]", "*")); // I l*v* J*v*
split(regex)
1String csv = "Rahul,Ankit,Aman,Priya"; 2String[] names = csv.split(","); 3 4for (String name : names) { 5 System.out.println(name); 6} 7// Output: Rahul, Ankit, Aman, Priya
trim() — Remove Whitespace
1String text = " Java Programming "; 2System.out.println("[" + text.trim() + "]"); // [Java Programming]
isEmpty() / isBlank() (Java 11+)
1String a = ""; 2String b = " "; 3 4System.out.println(a.isEmpty()); // true (length == 0) 5System.out.println(b.isEmpty()); // false (has spaces) 6System.out.println(b.isBlank()); // true (only whitespace)
join(delimiter, elements) (Java 8+)
1String result = String.join(" - ", "Java", "Python", "C++"); 2System.out.println(result); // Java - Python - C++ 3 4String[] langs = {"Java", "Python", "Go"}; 5System.out.println(String.join(", ", langs)); // Java, Python, Go
format() / formatted() (Java 15+)
1String name = "Rahul"; 2int age = 25; 3String info = String.format("Name: %s, Age: %d", name, age); 4System.out.println(info); // Name: Rahul, Age: 25
repeat(count) (Java 11+)
1String line = "-".repeat(20); 2System.out.println(line); // --------------------
String Comparison: == vs equals()
This is the most misunderstood concept in Java string handling. Let us settle it permanently.
| Operator | What It Compares | Use For |
|---|---|---|
== | Memory addresses (references) | Checking if two references point to the exact same object |
equals() | Actual character content | Checking if two strings have the same text |
equalsIgnoreCase() | Content ignoring case | Case-insensitive comparison |
Example: The Full Picture
1public class StringComparison { 2 public static void main(String[] args) { 3 String a = "Java"; 4 String b = "Java"; 5 String c = new String("Java"); 6 String d = new String("Java"); 7 8 // Reference comparison 9 System.out.println("a == b: " + (a == b)); // true (same pool object) 10 System.out.println("c == d: " + (c == d)); // false (different heap objects) 11 12 // Content comparison 13 System.out.println("a.equals(c): " + a.equals(c)); // true (same text) 14 System.out.println("c.equals(d): " + c.equals(d)); // true (same text) 15 16 // Case insensitive 17 System.out.println("JAVA".equalsIgnoreCase("java")); // true 18 } 19}
Best Practice
Always use
equals()orequalsIgnoreCase()to compare string content. Use==only when you intentionally want to check if two variables reference the exact same object (rare in application code).
The Null-Safe Comparison Pattern
1String input = null; 2 3// DANGEROUS — NullPointerException! 4if (input.equals("Java")) { } 5 6// SAFE — Put the literal first 7if ("Java".equals(input)) { } 8// If input is null, this simply returns false — no crash!
Regular Expressions (Regex)
Regular Expressions are patterns used to match, search, validate, and manipulate text. Java provides regex support through java.util.regex.Pattern and java.util.regex.Matcher.
Simple Validation with matches()
For basic validation, use the built-in String.matches() method:
1String phone = "9876543210"; 2System.out.println(phone.matches("\\d{10}")); // true (exactly 10 digits)
Common Regex Patterns
| Pattern | Matches | Example |
|---|---|---|
\\d | Any digit (0-9) | \\d+ → one or more digits |
\\D | Any non-digit | \\D+ → one or more non-digits |
\\w | Word character (a-z, A-Z, 0-9, _) | \\w+ → word |
\\W | Non-word character | \\W → special chars |
\\s | Whitespace | \\s+ → one or more spaces |
\\S | Non-whitespace | \\S+ → non-space text |
[a-z] | Lowercase letter | [a-z]+ → lowercase word |
[A-Z] | Uppercase letter | [A-Z]+ → uppercase word |
[A-Za-z0-9] | Alphanumeric | [A-Za-z0-9]+ → alphanumeric |
Pattern and Matcher (For Advanced Use)
1import java.util.regex.*; 2 3public class RegexAdvanced { 4 public static void main(String[] args) { 5 String text = "Contact us at support@tech3space.com or sales@tech3space.com"; 6 7 String emailPattern = "[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"; 8 Pattern pattern = Pattern.compile(emailPattern); 9 Matcher matcher = pattern.matcher(text); 10 11 System.out.println("Emails found:"); 12 while (matcher.find()) { 13 System.out.println("→ " + matcher.group()); 14 } 15 } 16}
Output:
1Emails found: 2→ support@tech3space.com 3→ sales@tech3space.com
Practical Regex Examples
1// Email validation 2String email = "user@example.com"; 3boolean validEmail = email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"); 4 5// Phone number (Indian format) 6String phone = "+91-98765-43210"; 7boolean validPhone = phone.matches("^(\\+91[-\\s]?)?[6-9]\\d{9}$"); 8 9// Strong password 10String password = "Java@1234"; 11boolean strong = password.matches("^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@#$%^&+=]).{8,}$");
Real-World Use Cases
Use Case 1: Password Strength Validator
1public class PasswordValidator { 2 3 static String validatePassword(String password) { 4 if (password == null || password.length() < 8) { 5 return "❌ Too short (min 8 chars)"; 6 } 7 if (!password.matches(".*[A-Z].*")) { 8 return "❌ Missing uppercase letter"; 9 } 10 if (!password.matches(".*[a-z].*")) { 11 return "❌ Missing lowercase letter"; 12 } 13 if (!password.matches(".*\\d.*")) { 14 return "❌ Missing digit"; 15 } 16 if (!password.matches(".*[@#$%^&+=!].*")) { 17 return "❌ Missing special character"; 18 } 19 return "✅ Strong password!"; 20 } 21 22 public static void main(String[] args) { 23 System.out.println(validatePassword("weak")); // Too short 24 System.out.println(validatePassword("Password1")); // Missing special char 25 System.out.println(validatePassword("Pass@1234")); // Strong 26 } 27}
Use Case 2: CSV Parser
1public class CsvParser { 2 public static void main(String[] args) { 3 String csv = "Rahul,25,Engineer,Mumbai\nPriya,30,Doctor,Delhi\nAmit,22,Student,Pune"; 4 String[] rows = csv.split("\\n"); 5 6 System.out.printf("%-10s %-5s %-12s %-10s%n", "Name", "Age", "Profession", "City"); 7 System.out.println("-".repeat(40)); 8 9 for (String row : rows) { 10 String[] cols = row.split(","); 11 System.out.printf("%-10s %-5s %-12s %-10s%n", cols[0], cols[1], cols[2], cols[3]); 12 } 13 } 14}
Use Case 3: URL Slug Generator
1public class SlugGenerator { 2 public static void main(String[] args) { 3 String title = "Java Strings Tutorial: Complete Beginner Guide!"; 4 5 String slug = title.toLowerCase() 6 .replaceAll("[^a-z0-9\\s]", "") // Remove special chars 7 .trim() 8 .replaceAll("\\s+", "-"); // Spaces to hyphens 9 10 System.out.println(slug); // java-strings-tutorial-complete-beginner-guide 11 } 12}
Common Mistakes
Mistake 1: Using == for Content Comparison
1// WRONG 2String a = new String("Java"); 3String b = new String("Java"); 4if (a == b) { // false! Different objects. 5 System.out.println("Equal"); 6} 7 8// CORRECT 9if (a.equals(b)) { // true! Same content. 10 System.out.println("Equal"); 11}
Mistake 2: Concatenating in Loops with String
1// WRONG — O(n²) time, creates n intermediate objects 2String result = ""; 3for (int i = 0; i < 10000; i++) { 4 result += "item" + i; // Disaster for performance! 5} 6 7// CORRECT — O(n) time, single buffer 8StringBuilder sb = new StringBuilder(); 9for (int i = 0; i < 10000; i++) { 10 sb.append("item").append(i); 11} 12String result = sb.toString();
Mistake 3: Calling Methods on Null Strings
1String input = null; 2 3// WRONG — NullPointerException! 4int len = input.length(); 5boolean eq = input.equals("test"); 6 7// CORRECT — Null check first 8if (input != null) { 9 int len = input.length(); 10} 11 12// Or use null-safe comparison 13if ("test".equals(input)) { // Safe even if input is null 14}
Mistake 4: Modifying StringBuilder Returned from Method
1// DANGEROUS — The caller can modify your internal state! 2public StringBuilder getConfig() { 3 return configBuilder; // Exposes internal mutable object! 4} 5 6// CORRECT — Return an immutable copy 7public String getConfig() { 8 return configBuilder.toString(); // Returns immutable String 9}
Mistake 5: Using StringBuffer Unnecessarily
1// WRONG — Synchronization overhead for no reason 2StringBuffer sb = new StringBuffer(); 3 4// CORRECT — StringBuilder is faster for single-threaded code 5StringBuilder sb = new StringBuilder();
Mistake 6: Forgetting split() Uses Regex
1// WRONG — "\\." splits on regex, not literal dot 2String[] parts = "192.168.1.1".split("."); // ❌ Splits on ANY character! 3 4// CORRECT — Escape the dot in regex 5String[] parts = "192.168.1.1".split("\\."); // ✅ ["192", "168", "1", "1"]
Best Practices
-
Use string literals, not
new String()— Leverage the String Pool.1// Good 2String name = "Java"; 3 4// Avoid 5String name = new String("Java"); -
Use
equals()for content comparison — Never use==unless comparing references intentionally. -
Use
StringBuilderfor loop concatenation — The performance difference is massive.1StringBuilder sb = new StringBuilder(); 2for (String item : items) { 3 sb.append(item).append(", "); 4} -
Use
StringBufferonly for shared mutable strings — In multi-threaded contexts where synchronization is required. -
Put literals first in equals() — Prevents
NullPointerException.1if ("expected".equals(userInput)) { } -
Use
isBlank()(Java 11+) overtrim().isEmpty()— Cleaner and handles Unicode whitespace.1// Good 2if (input.isBlank()) { } 3 4// Old way 5if (input == null || input.trim().isEmpty()) { } -
Use
String.join()for delimited lists — Cleaner than manual loops.1String csv = String.join(", ", names); -
Pre-size StringBuilder when possible — Reduces resizing overhead.
1StringBuilder sb = new StringBuilder(1000); // Start with 1KB capacity -
Validate with regex, but sanitize with code — Regex is great for format validation, but never rely on it alone for security.
-
Use
String.format()for complex output — More readable than concatenation.1String result = String.format("User %s (ID: %d) logged in at %s", name, id, time);
Architecture & Performance Considerations
How Strings Are Stored Internally
Modern Java (9+) stores strings using a byte array (byte[]) with a coder flag:
- LATIN1 (1 byte per char) for strings containing only ISO-8859-1 characters
- UTF16 (2 bytes per char) for strings with characters outside that range
This optimization saves ~50% memory for English text compared to older Java versions that always used char[] (2 bytes per character).
StringBuilder Capacity Growth
StringBuilder starts with a default capacity of 16 characters. When full, it creates a new array double the size and copies existing content.
1StringBuilder sb = new StringBuilder(); // Capacity: 16 2sb.append("1234567890123456"); // Full! 3sb.append("7"); // Capacity doubles to 32
Performance Tip: If you know the final size, specify it in the constructor to avoid resizing:
1StringBuilder sb = new StringBuilder(10000);
String Concatenation: Compiler Magic
The Java compiler automatically converts + concatenation into StringBuilder operations in simple cases:
1// Source code 2String result = "Hello" + name + "!"; 3 4// Compiled equivalent 5String result = new StringBuilder() 6 .append("Hello") 7 .append(name) 8 .append("!") 9 .toString();
However, this optimization does not apply inside loops — that is where manual StringBuilder is critical.
String.intern() and Memory Management
Manual interning with .intern() can save memory but increases the permanent generation / metaspace usage. In modern Java with G1 garbage collector, the String Pool is garbage-collectible, but excessive interning can still cause memory pressure.
String Immutability and Security
Because strings are immutable, they are safe to use as:
- Map keys — Hash code never changes
- Network credentials — Cannot be modified after creation
- File paths — Cannot be tampered with
For passwords, however, consider using char[] instead of String so you can manually overwrite the memory after use:
1// More secure for passwords 2char[] password = console.readPassword("Password: "); 3// ... use password ... 4java.util.Arrays.fill(password, ' '); // Clear from memory
Practice Programs
Exercise 1: Character Frequency Counter
1import java.util.Scanner; 2 3public class CharFrequency { 4 public static void main(String[] args) { 5 try (Scanner input = new Scanner(System.in)) { 6 System.out.print("Enter text: "); 7 String text = input.nextLine().toLowerCase(); 8 9 int[] freq = new int[26]; 10 for (char c : text.toCharArray()) { 11 if (c >= 'a' && c <= 'z') { 12 freq[c - 'a']++; 13 } 14 } 15 16 System.out.println("\\nCharacter Frequencies:"); 17 for (int i = 0; i < 26; i++) { 18 if (freq[i] > 0) { 19 System.out.println((char) (i + 'a') + ": " + freq[i]); 20 } 21 } 22 } 23 } 24}
Exercise 2: Reverse Words in a Sentence
1import java.util.Scanner; 2 3public class ReverseWords { 4 public static void main(String[] args) { 5 try (Scanner input = new Scanner(System.in)) { 6 System.out.print("Enter sentence: "); 7 String sentence = input.nextLine(); 8 9 String[] words = sentence.split("\\s+"); 10 StringBuilder reversed = new StringBuilder(); 11 12 for (int i = words.length - 1; i >= 0; i--) { 13 reversed.append(words[i]); 14 if (i > 0) reversed.append(" "); 15 } 16 17 System.out.println("Reversed: " + reversed); 18 } 19 } 20}
Exercise 3: Vowel and Consonant Counter
1import java.util.Scanner; 2 3public class VowelConsonant { 4 public static void main(String[] args) { 5 try (Scanner input = new Scanner(System.in)) { 6 System.out.print("Enter text: "); 7 String text = input.nextLine().toLowerCase(); 8 9 int vowels = 0, consonants = 0; 10 for (char c : text.toCharArray()) { 11 if (Character.isLetter(c)) { 12 if ("aeiou".indexOf(c) >= 0) { 13 vowels++; 14 } else { 15 consonants++; 16 } 17 } 18 } 19 20 System.out.println("Vowels: " + vowels); 21 System.out.println("Consonants: " + consonants); 22 } 23 } 24}
Exercise 4: Username Validator with Regex
1import java.util.Scanner; 2 3public class UsernameValidator { 4 public static void main(String[] args) { 5 try (Scanner input = new Scanner(System.in)) { 6 System.out.print("Enter username: "); 7 String username = input.nextLine(); 8 9 // Starts with letter, 5-15 chars, letters/digits/underscores only 10 boolean valid = username.matches("^[a-zA-Z][a-zA-Z0-9_]{4,14}$"); 11 12 if (valid) { 13 System.out.println("✅ Valid username!"); 14 } else { 15 System.out.println("❌ Invalid username."); 16 System.out.println("Rules: Start with a letter, 5-15 chars, letters/digits/underscores only."); 17 } 18 } 19 } 20}
Exercise 5: String Compression (Run-Length Encoding)
1public class StringCompression { 2 public static void main(String[] args) { 3 String input = "aaabbcccc"; 4 StringBuilder compressed = new StringBuilder(); 5 6 int count = 1; 7 for (int i = 1; i <= input.length(); i++) { 8 if (i < input.length() && input.charAt(i) == input.charAt(i - 1)) { 9 count++; 10 } else { 11 compressed.append(input.charAt(i - 1)).append(count); 12 count = 1; 13 } 14 } 15 16 System.out.println("Input: " + input); 17 System.out.println("Output: " + compressed); // a3b2c4 18 } 19}
Mini Project: Text Processing Toolkit
Build a comprehensive console application that demonstrates string methods, StringBuilder, regex, and text analysis.
1import java.util.Scanner; 2import java.util.regex.*; 3 4public class TextProcessingToolkit { 5 6 static void printHeader(String title) { 7 System.out.println("\\n" + "=".repeat(50)); 8 System.out.println(" " + title); 9 System.out.println("=".repeat(50)); 10 } 11 12 static void analyzeText(String text) { 13 printHeader("TEXT ANALYSIS"); 14 15 int chars = text.length(); 16 int words = text.isBlank() ? 0 : text.trim().split("\\s+").length; 17 int sentences = text.split("[.!?]+").length - (text.endsWith(".") || text.endsWith("!") || text.endsWith("?") ? 0 : 1); 18 sentences = Math.max(1, sentences); 19 20 int vowels = 0, consonants = 0, digits = 0, special = 0; 21 for (char c : text.toLowerCase().toCharArray()) { 22 if ("aeiou".indexOf(c) >= 0) vowels++; 23 else if (c >= 'a' && c <= 'z') consonants++; 24 else if (c >= '0' && c <= '9') digits++; 25 else if (!Character.isWhitespace(c)) special++; 26 } 27 28 System.out.println("Characters: " + chars); 29 System.out.println("Words: " + words); 30 System.out.println("Sentences: " + sentences); 31 System.out.println("Vowels: " + vowels); 32 System.out.println("Consonants: " + consonants); 33 System.out.println("Digits: " + digits); 34 System.out.println("Special Chars:" + special); 35 } 36 37 static void validateInputs(String text) { 38 printHeader("INPUT VALIDATION"); 39 40 boolean hasEmail = text.matches(".*[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}.*"); 41 boolean hasPhone = text.matches(".*\\b[6-9]\\d{9}\\b.*"); 42 boolean hasUrl = text.matches(".*https?://[^\\s]+.*"); 43 44 System.out.println("Contains Email: " + (hasEmail ? "✅ Yes" : "❌ No")); 45 System.out.println("Contains Phone: " + (hasPhone ? "✅ Yes" : "❌ No")); 46 System.out.println("Contains URL: " + (hasUrl ? "✅ Yes" : "❌ No")); 47 } 48 49 static void formatText(String text) { 50 printHeader("FORMATTED OUTPUT"); 51 52 // Title case 53 String[] words = text.toLowerCase().split("\\s+"); 54 StringBuilder titleCase = new StringBuilder(); 55 for (String word : words) { 56 if (!word.isEmpty()) { 57 titleCase.append(Character.toUpperCase(word.charAt(0))) 58 .append(word.substring(1)) 59 .append(" "); 60 } 61 } 62 System.out.println("Title Case: " + titleCase.toString().trim()); 63 64 // Camel case (no spaces, each word capitalized) 65 StringBuilder camelCase = new StringBuilder(); 66 for (int i = 0; i < words.length; i++) { 67 if (!words[i].isEmpty()) { 68 if (i == 0) { 69 camelCase.append(words[i].toLowerCase()); 70 } else { 71 camelCase.append(Character.toUpperCase(words[i].charAt(0))) 72 .append(words[i].substring(1).toLowerCase()); 73 } 74 } 75 } 76 System.out.println("Camel Case: " + camelCase); 77 78 // Slug 79 String slug = text.toLowerCase() 80 .replaceAll("[^a-z0-9\\s]", "") 81 .trim() 82 .replaceAll("\\s+", "-"); 83 System.out.println("URL Slug: " + slug); 84 } 85 86 static void findAndReplace(String text, String find, String replace) { 87 printHeader("FIND & REPLACE"); 88 int count = 0; 89 int index = 0; 90 StringBuilder result = new StringBuilder(); 91 92 while ((index = text.indexOf(find, index)) != -1) { 93 count++; 94 index += find.length(); 95 } 96 97 System.out.println("Occurrences of \"" + find + "\": " + count); 98 System.out.println("After replacement: " + text.replace(find, replace)); 99 } 100 101 public static void main(String[] args) { 102 try (Scanner input = new Scanner(System.in)) { 103 System.out.println("📝 TEXT PROCESSING TOOLKIT"); 104 System.out.print("\\nEnter your text: "); 105 String text = input.nextLine(); 106 107 boolean running = true; 108 while (running) { 109 System.out.println("\\n--- MENU ---"); 110 System.out.println("1. Analyze Text"); 111 System.out.println("2. Validate Inputs (Email/Phone/URL)"); 112 System.out.println("3. Format Text (Title/Camel/Slug)"); 113 System.out.println("4. Find & Replace"); 114 System.out.println("5. Reverse Text"); 115 System.out.println("6. Word Frequency"); 116 System.out.println("7. Exit"); 117 System.out.print("Choice: "); 118 119 int choice = Integer.parseInt(input.nextLine()); 120 121 switch (choice) { 122 case 1 -> analyzeText(text); 123 case 2 -> validateInputs(text); 124 case 3 -> formatText(text); 125 case 4 -> { 126 System.out.print("Find: "); 127 String find = input.nextLine(); 128 System.out.print("Replace with: "); 129 String replace = input.nextLine(); 130 findAndReplace(text, find, replace); 131 } 132 case 5 -> { 133 printHeader("REVERSED TEXT"); 134 System.out.println(new StringBuilder(text).reverse()); 135 } 136 case 6 -> { 137 printHeader("WORD FREQUENCY"); 138 String[] words = text.toLowerCase().split("\\s+"); 139 java.util.Arrays.sort(words); 140 int count = 1; 141 for (int i = 1; i <= words.length; i++) { 142 if (i < words.length && words[i].equals(words[i - 1])) { 143 count++; 144 } else { 145 System.out.println(words[i - 1] + ": " + count); 146 count = 1; 147 } 148 } 149 } 150 case 7 -> { 151 System.out.println("👋 Goodbye!"); 152 running = false; 153 } 154 default -> System.out.println("❌ Invalid choice."); 155 } 156 } 157 } 158 } 159}
What This Project Covers:
- String methods:
length(),split(),toLowerCase(),toUpperCase(),charAt(),substring(),indexOf(),replace() StringBuilderfor efficient text building and reversing- Regex for email, phone, and URL detection
- Text analysis: word count, sentence count, character classification
- Text formatting: title case, camel case, URL slug generation
- Word frequency counting with sorting
- Interactive menu system
Summary & Cheat Sheet
Quick Reference
| Task | Method | Example |
|---|---|---|
| Create | Literal or new | String s = "Java"; |
| Length | length() | s.length() |
| Character | charAt(i) | s.charAt(0) |
| Substring | substring(i) or substring(i,j) | s.substring(2, 5) |
| Uppercase | toUpperCase() | s.toUpperCase() |
| Lowercase | toLowerCase() | s.toLowerCase() |
| Contains | contains(str) | s.contains("ava") |
| Starts/Ends | startsWith() / endsWith() | s.endsWith(".java") |
Key Takeaways
- Strings are immutable — Every "modification" creates a new object.
- Use the String Pool — Prefer literals (
"text") overnew String("text"). - Never concatenate in loops with
+— UseStringBuilderinstead. - Use
equals()for content comparison —==compares memory addresses.