Programming in Java

Unit 7: String & StringBuilder

From UPI ID validation to text analytics — master Java's String immutability, every String method, StringBuilder mutability, and start building real text-processing tools for Indian fintech.

⏱️ Time to Complete: 5 hrs theory + 4 hrs lab  |  💰 Earning Potential: ₹5K–₹20K/month  |  📝 30 MCQs (Bloom's Mapped)

💼 Jobs this unlocks: Java Developer (₹4–8 LPA)  |  Backend Engineer (₹6–12 LPA)  |  QA Automation (₹3–6 LPA)

Section A

Opening Hook — Every UPI Payment Runs Through Java Strings

📱 How PhonePe Validates Your UPI ID in Milliseconds

Every time you type a UPI ID like rahul@ybl or priya.sharma@oksbi into PhonePe, a Java backend validates it instantly. The system calls upiId.contains("@") to check the @ symbol, uses upiId.split("@") to separate the username from the handle, and runs regex matching to verify the handle against registered PSPs like @ybl, @paytm, @oksbi, @ibl.

India's UPI ecosystem processed 14.04 billion transactions worth ₹20.64 lakh crore in a single month (March 2025). Behind every single one of those transactions, Java Strings are at work — parsing, validating, formatting, logging. The String class is the most used class in the entire Java ecosystem.

What if YOU could build this? What if you understood exactly how equals() differs from ==, why Strings are immutable, and how StringBuilder makes your code 100× faster? That's exactly what this chapter teaches you.

🇮🇳 PhonePe🇮🇳 Google Pay🇮🇳 Paytm🇮🇳 BHIM🇮🇳 Razorpay🇮🇳 NPCI
A typical Java enterprise application creates over 10,000 String objects per second. In server-side applications like those running India's UPI infrastructure, Strings account for 25–40% of heap memory usage. Understanding String pooling and StringBuilder isn't just academic — it's the difference between a server handling 1,000 requests/second vs 10,000. Google estimates that String-related optimizations alone saved them $50 million/year in cloud compute costs.
Section B

Learning Outcomes — Bloom's Taxonomy Mapped (12 Outcomes)

Bloom's LevelLearning Outcome
🔵 RememberDefine String immutability and explain why Java Strings cannot be changed after creation
🔵 RememberList all major String class constructors and at least 15 String methods with their signatures
🔵 UnderstandExplain the String pool memory model and how Java reuses String literals to save memory
🔵 UnderstandDescribe the difference between ==, equals(), and compareTo() with concrete examples
🟢 ApplyUse String methods (contains, split, matches) to validate Indian UPI IDs programmatically
🟢 ApplyImplement StringBuilder for efficient string concatenation in loops and dynamic text building
🟢 AnalyzeCompare String vs StringBuilder vs StringBuffer in terms of mutability, thread-safety, and performance
🟢 AnalyzeAnalyze memory implications of String concatenation in loops vs StringBuilder.append()
🟠 EvaluateJustify when to use StringBuilder over String concatenation based on performance profiling
🟠 EvaluateAssess the trade-offs between regex-based vs manual String parsing for input validation
🟠 CreateBuild a complete CSV parser that reads, splits, and processes structured text data using String methods
🟠 CreateDesign a full-featured text processing utility combining String and StringBuilder for real-world tasks
Section C

Concept Explanation — String & StringBuilder from Scratch

1. String Immutability & Memory Model

In Java, a String is immutable — once created, its value can never be changed. When you write s = s + " world", you're NOT modifying the original String. Java creates a brand-new String object and points s to it. The old String stays in memory until garbage collected.

Indian Analogy: String pool = hostel common room. Imagine your college hostel has a common room with a bookshelf. If your friend already has a copy of "Let Us C" on the shelf, you don't buy a new one — you just share the same book. That's the String pool. When you write String s1 = "hello" and later String s2 = "hello", Java doesn't create two objects — both s1 and s2 point to the SAME "hello" in the String pool. But if you write new String("hello"), it's like buying your own copy even though one exists — wasteful!

🧠 String Pool (Intern Pool) — Memory Model

How It Works:

Java maintains a special memory area called the String Pool (or String Intern Pool) inside the Heap. When you create a String using a literal (e.g., "hello"), Java first checks the pool. If "hello" already exists, it returns a reference to the existing object. If not, it creates a new String in the pool.

Memory Diagram (Text Representation):
Memory
// Code:
String s1 = "hello";        // → Pool: creates "hello"
String s2 = "hello";        // → Pool: reuses same "hello"
String s3 = new String("hello"); // → Heap: NEW object (outside pool)

/*
  ┌──────────── HEAP MEMORY ────────────┐
  │                                      │
  │   ┌──── STRING POOL ────┐           │
  │   │                     │           │
  │   │   ┌───────────┐    │           │
  │   │   │  "hello"  │◄───┼── s1      │
  │   │   └───────────┘    │◄── s2     │
  │   │                     │           │
  │   └─────────────────────┘           │
  │                                      │
  │   ┌───────────┐                     │
  │   │  "hello"  │◄────────── s3       │
  │   └───────────┘  (separate object)  │
  │                                      │
  └──────────────────────────────────────┘

  s1 == s2  → true  (same reference in pool)
  s1 == s3  → false (different objects)
  s1.equals(s3) → true (same content)
*/
Why Immutability Matters:

1. Security: Strings are used for passwords, DB connections, file paths. If Strings were mutable, a malicious function could change a filename after security checks pass.

2. Thread-Safety: Immutable objects are inherently thread-safe. Multiple threads can share the same String without synchronization — critical for PhonePe processing thousands of UPI transactions simultaneously.

3. Caching/Hashing: Since Strings never change, their hashCode() can be cached. HashMap keys are almost always Strings — cached hash codes make lookups blazing fast.

4. String Pool Efficiency: Immutability makes the String pool safe. If Strings were mutable and s1 changed "hello" to "world", s2 would also change — disaster!

String concatenation in loops creates garbage! Every s = s + "x" inside a loop creates a NEW String object. In a loop of 10,000 iterations, that's 10,000 throwaway objects clogging memory. Always use StringBuilder inside loops.
// ❌ BAD — creates 10,000 String objects
String result = "";
for (int i = 0; i < 10000; i++) {
    result = result + i;  // New object every iteration!
}

// ✅ GOOD — single mutable object
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append(i);  // Same object modified
}
String result = sb.toString();

2. String Constructors

Java
// 1. Empty String
String s1 = new String();                // s1 = ""

// 2. From another String
String s2 = new String("Namaste");     // s2 = "Namaste"

// 3. From char array
char[] chars = {'J', 'a', 'v', 'a'};
String s3 = new String(chars);          // s3 = "Java"

// 4. From char array with offset and count
String s4 = new String(chars, 1, 2);    // s4 = "av" (start at index 1, take 2 chars)

// 5. From byte array
byte[] bytes = {72, 101, 108, 108, 111};
String s5 = new String(bytes);          // s5 = "Hello"

// 6. From StringBuilder
StringBuilder sb = new StringBuilder("India");
String s6 = new String(sb);              // s6 = "India"

// 7. Most common — String literal (uses String pool)
String s7 = "PhonePe";                  // Preferred! Uses pool.
Always prefer String literals over new String(). Writing String s = "hello" uses the String pool (efficient). Writing String s = new String("hello") creates an unnecessary extra object on the heap. The only time you'd use new String() is when constructing from char/byte arrays.

3. String Methods — Complete Reference

3.1 Length & Character Access

Java
String city = "Bengaluru";

// length() — number of characters
System.out.println(city.length());          // 9

// charAt(index) — character at position
System.out.println(city.charAt(0));          // B
System.out.println(city.charAt(5));          // l

// toCharArray() — convert to char array
char[] arr = city.toCharArray();
for (char c : arr) System.out.print(c + " ");
// B e n g a l u r u

3.2 Searching

Java
String upi = "rahul.kumar@ybl";

// indexOf(String) — first occurrence position (-1 if not found)
System.out.println(upi.indexOf("@"));         // 11
System.out.println(upi.indexOf("xyz"));       // -1

// lastIndexOf(String) — last occurrence position
String path = "com.paytm.app.Main";
System.out.println(path.lastIndexOf("."));    // 14

// contains(CharSequence) — true/false check
System.out.println(upi.contains("@"));        // true
System.out.println(upi.contains("paytm"));    // false

// startsWith(String) and endsWith(String)
System.out.println(upi.startsWith("rahul"));  // true
System.out.println(upi.endsWith("@ybl"));     // true
System.out.println(upi.endsWith("@paytm"));   // false

3.3 Extraction

Java
String aadhaar = "1234-5678-9012";

// substring(beginIndex) — from index to end
System.out.println(aadhaar.substring(5));       // 5678-9012

// substring(beginIndex, endIndex) — from begin to end-1
System.out.println(aadhaar.substring(0, 4));   // 1234
System.out.println(aadhaar.substring(5, 9));   // 5678

3.4 Comparison — The Most Important Section

Java
// equals() — compares CONTENT
String a = "Java";
String b = new String("Java");
System.out.println(a.equals(b));              // true  (same content)

// == — compares REFERENCE (memory address)
System.out.println(a == b);                   // false (different objects!)

// equalsIgnoreCase() — case-insensitive content check
System.out.println("JAVA".equalsIgnoreCase("java")); // true

// compareTo() — lexicographic comparison (returns int)
System.out.println("Apple".compareTo("Banana"));  // negative (A < B)
System.out.println("Cat".compareTo("Cat"));      // 0 (equal)
System.out.println("Dog".compareTo("Cat"));      // positive (D > C)

3.5 Modification (Returns New String)

Java
String name = "  Rahul Sharma  ";

// trim() — removes leading/trailing whitespace
System.out.println(name.trim());               // "Rahul Sharma"

// toUpperCase() and toLowerCase()
System.out.println("india".toUpperCase());      // "INDIA"
System.out.println("JAVA".toLowerCase());       // "java"

// replace(old, new) — replace all occurrences
String phone = "98765-43210";
System.out.println(phone.replace("-", ""));    // "9876543210"
System.out.println(phone.replace('9', 'X'));  // "X8765-43210"

// replaceAll(regex, replacement)
String data = "Price: Rs.500, Tax: Rs.90";
System.out.println(data.replaceAll("[0-9]+", "***"));
// "Price: Rs.***, Tax: Rs.***"

3.6 Splitting & Joining

Java
// split(regex) — break string into array
String csv = "Rahul,BCA,Mumbai,8.5";
String[] parts = csv.split(",");
System.out.println(parts[0]);  // Rahul
System.out.println(parts[1]);  // BCA
System.out.println(parts[2]);  // Mumbai
System.out.println(parts[3]);  // 8.5

// String.join(delimiter, elements) — combine with separator
String result = String.join(" | ", "PhonePe", "GPay", "Paytm");
System.out.println(result);  // PhonePe | GPay | Paytm

// split with limit
String upi = "rahul.kumar@ybl";
String[] upiParts = upi.split("@", 2);
System.out.println("Username: " + upiParts[0]);  // rahul.kumar
System.out.println("Handle: " + upiParts[1]);    // ybl

3.7 Conversion & Formatting

Java
// valueOf() — convert other types to String
String numStr = String.valueOf(42);           // "42"
String boolStr = String.valueOf(true);       // "true"
String dblStr = String.valueOf(3.14);        // "3.14"

// format() — formatted String (like printf)
String msg = String.format("Name: %s, Age: %d, CGPA: %.1f",
                           "Priya", 21, 8.754);
System.out.println(msg);
// Name: Priya, Age: 21, CGPA: 8.8

3.8 Checking

Java
// isEmpty() — true if length is 0
System.out.println("".isEmpty());       // true
System.out.println(" ".isEmpty());      // false (has a space)

// isBlank() — true if empty or only whitespace (Java 11+)
System.out.println("   ".isBlank());   // true
System.out.println("Hi".isBlank());    // false

4. String Comparison Deep-Dive: == vs equals() vs compareTo()

This is the #1 most-asked topic in Java interviews and MCQ exams. Getting this wrong in a TCS NQT or Infosys exam means losing easy marks. Let's break it down with tricky examples:

Operator/MethodWhat It ComparesReturnsWhen to Use
==Memory reference (address)booleanChecking if two variables point to the SAME object
equals()Content (character by character)booleanChecking if two Strings have the SAME text (✅ USE THIS)
equalsIgnoreCase()Content ignoring casebooleanCase-insensitive comparison (user input validation)
compareTo()Lexicographic (dictionary) orderint (−, 0, +)Sorting, ordering, finding which comes first

Tricky Example 1: String Pool Trap

Java
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");

System.out.println(s1 == s2);       // true  — both from pool, same reference
System.out.println(s1 == s3);       // false — s3 is on heap, different reference
System.out.println(s1.equals(s3));  // true  — same content "hello"

Tricky Example 2: Concatenation Trap

Java
String s1 = "hello";
String s2 = "hel" + "lo";    // Compile-time constant → optimised to "hello"
String s3 = "hel";
String s4 = s3 + "lo";         // Runtime concatenation → NEW object

System.out.println(s1 == s2);   // true  — compiler optimises "hel" + "lo" to "hello"
System.out.println(s1 == s4);   // false — s4 created at runtime, new object
System.out.println(s1.equals(s4)); // true  — same content

Tricky Example 3: intern() Method

Java
String s1 = "hello";
String s2 = new String("hello");
String s3 = s2.intern();  // Returns pool reference of "hello"

System.out.println(s1 == s2);   // false — s2 is on heap
System.out.println(s1 == s3);   // true  — intern() returned the pool copy

Tricky Example 4: compareTo() Returns

Java
System.out.println("A".compareTo("B"));   // -1  (A comes before B)
System.out.println("B".compareTo("A"));   // +1  (B comes after A)
System.out.println("A".compareTo("A"));   // 0   (equal)
System.out.println("a".compareTo("A"));   // +32 (lowercase 'a' = 97, uppercase 'A' = 65)
System.out.println("Apple".compareTo("App")); // +2 (difference in length)
NEVER use == to compare String content! This is the #1 Java beginner mistake. == checks if two variables point to the SAME object in memory, not if they contain the same text. Always use .equals() for content comparison. In exam MCQs, 90% of String trick questions test exactly this.

5. StringBuilder — Mutable Strings

Since Strings are immutable, Java provides StringBuilder for situations where you need to modify text frequently. StringBuilder is mutable — you can change its content without creating new objects.

StringBuilder Constructors

Java
// Default capacity: 16 characters
StringBuilder sb1 = new StringBuilder();

// Custom initial capacity
StringBuilder sb2 = new StringBuilder(100);

// From String
StringBuilder sb3 = new StringBuilder("Hello");
System.out.println(sb3.capacity());  // 21 (16 + 5 chars of "Hello")

StringBuilder Methods

Java
StringBuilder sb = new StringBuilder("Hello");

// append() — add to end
sb.append(" World");         // "Hello World"
sb.append(2025);              // "Hello World2025"
sb.append('!');               // "Hello World2025!"

// insert(offset, data) — insert at position
sb = new StringBuilder("Hello World");
sb.insert(5, " Beautiful");  // "Hello Beautiful World"

// delete(start, end) — remove characters
sb.delete(5, 15);             // "Hello World"

// deleteCharAt(index)
sb = new StringBuilder("Hello!");
sb.deleteCharAt(5);           // "Hello"

// replace(start, end, str)
sb = new StringBuilder("Hello World");
sb.replace(6, 11, "India");  // "Hello India"

// reverse()
sb = new StringBuilder("MADAM");
sb.reverse();                 // "MADAM" (palindrome!)

// toString() — convert back to String
String result = sb.toString();

// capacity() and length()
sb = new StringBuilder();
System.out.println(sb.capacity());  // 16 (default)
System.out.println(sb.length());    // 0  (no chars yet)

// charAt(index) and setCharAt(index, char)
sb = new StringBuilder("Java");
System.out.println(sb.charAt(0));    // J
sb.setCharAt(0, 'L');              // "Lava"
Set initial capacity when you know approximate size. new StringBuilder(1000) avoids internal array resizing. When capacity is exceeded, StringBuilder creates a new array of size (old_capacity * 2) + 2 and copies everything — expensive! Pre-sizing prevents this.

6. String vs StringBuilder vs StringBuffer

FeatureStringStringBuilderStringBuffer
Mutability❌ Immutable✅ Mutable✅ Mutable
Thread-Safe✅ Yes (immutable)❌ Not thread-safe✅ Yes (synchronized)
PerformanceSlow for modifications⚡ FastestSlower than StringBuilder
MemoryCreates new objectsModifies in-placeModifies in-place
Packagejava.langjava.langjava.lang
SinceJDK 1.0JDK 1.5JDK 1.0
Use WhenContent won't changeSingle-thread modificationsMulti-thread modifications
Indian AnalogyCarved in stone (temple inscription)Whiteboard (erase & rewrite freely)Whiteboard with a guard (only one person writes at a time)

7. String Formatting (printf / format)

SpecifierMeaningExampleOutput
%sStringformat("%s", "Rahul")Rahul
%dIntegerformat("%d", 42)42
%fFloat/Doubleformat("%.2f", 3.14159)3.14
%cCharacterformat("%c", 'A')A
%bBooleanformat("%b", true)true
%nNewlineformat("Hi%nBye")Hi\nBye
%xHexadecimalformat("%x", 255)ff
%oOctalformat("%o", 8)10
%10sRight-align (width 10)format("%10s", "Hi")        Hi
%-10sLeft-align (width 10)format("%-10s", "Hi")Hi        
Java
// printf — prints formatted output directly
System.out.printf("Student: %-15s | CGPA: %.1f | Rank: %03d%n",
                  "Priya Sharma", 8.754, 5);
// Student: Priya Sharma    | CGPA: 8.8 | Rank: 005

// String.format — returns formatted String
String receipt = String.format(
    "UPI Txn: ₹%,.2f sent to %s via %s",
    1500.50, "rahul@ybl", "PhonePe"
);
System.out.println(receipt);
// UPI Txn: ₹1,500.50 sent to rahul@ybl via PhonePe

8. Complete Programs

Program 1: Palindrome Checker

Java
public class PalindromeChecker {
    public static boolean isPalindrome(String str) {
        str = str.toLowerCase().replaceAll("[^a-z0-9]", "");
        String reversed = new StringBuilder(str).reverse().toString();
        return str.equals(reversed);
    }

    public static void main(String[] args) {
        String[] tests = {"MADAM", "RaceCar", "Hello", "A man a plan a canal Panama"};
        for (String test : tests) {
            System.out.printf("%-35s → %s%n", "\"" + test + "\"",
                isPalindrome(test) ? "✅ Palindrome" : "❌ Not Palindrome");
        }
    }
}
"MADAM" → ✅ Palindrome "RaceCar" → ✅ Palindrome "Hello" → ❌ Not Palindrome "A man a plan a canal Panama" → ✅ Palindrome

Program 2: Anagram Detector

Java
import java.util.Arrays;

public class AnagramDetector {
    public static boolean areAnagrams(String s1, String s2) {
        s1 = s1.toLowerCase().replaceAll("\\s", "");
        s2 = s2.toLowerCase().replaceAll("\\s", "");
        if (s1.length() != s2.length()) return false;
        char[] arr1 = s1.toCharArray();
        char[] arr2 = s2.toCharArray();
        Arrays.sort(arr1);
        Arrays.sort(arr2);
        return Arrays.equals(arr1, arr2);
    }

    public static void main(String[] args) {
        System.out.println(areAnagrams("listen", "silent"));     // true
        System.out.println(areAnagrams("Triangle", "Integral")); // true
        System.out.println(areAnagrams("Hello", "World"));      // false
        System.out.println(areAnagrams("Dormitory", "Dirty Room")); // true
    }
}
true true false true

Program 3: CSV Parser

Java
public class CSVParser {
    public static void main(String[] args) {
        String[] csvData = {
            "Rahul Sharma,BCA,Mumbai,8.5,PhonePe",
            "Priya Patel,B.Tech,Ahmedabad,9.1,Google",
            "Amit Kumar,MCA,Delhi,7.8,Paytm",
            "Sneha Reddy,BCA,Hyderabad,8.9,Infosys"
        };

        System.out.printf("%-18s %-8s %-14s %-6s %-10s%n",
                          "NAME", "COURSE", "CITY", "CGPA", "COMPANY");
        System.out.println("─".repeat(60));

        double totalCgpa = 0;
        int count = 0;

        for (String line : csvData) {
            String[] fields = line.split(",");
            String name = fields[0].trim();
            String course = fields[1].trim();
            String city = fields[2].trim();
            double cgpa = Double.parseDouble(fields[3].trim());
            String company = fields[4].trim();

            System.out.printf("%-18s %-8s %-14s %-6.1f %-10s%n",
                              name, course, city, cgpa, company);
            totalCgpa += cgpa;
            count++;
        }

        System.out.println("─".repeat(60));
        System.out.printf("Average CGPA: %.2f%n", totalCgpa / count);
    }
}
NAME COURSE CITY CGPA COMPANY ──────────────────────────────────────────────────────────── Rahul Sharma BCA Mumbai 8.5 PhonePe Priya Patel B.Tech Ahmedabad 9.1 Google Amit Kumar MCA Delhi 7.8 Paytm Sneha Reddy BCA Hyderabad 8.9 Infosys ──────────────────────────────────────────────────────────── Average CGPA: 8.58

Program 4: UPI ID Validator

Java
public class UPIIDValidator {
    static final String[] VALID_HANDLES = {
        "ybl", "paytm", "oksbi", "okaxis", "okhdfcbank",
        "okicici", "ibl", "axl", "sbi", "upi", "apl"
    };

    public static String validate(String upiId) {
        if (upiId == null || upiId.isEmpty()) return "❌ Empty UPI ID";
        upiId = upiId.trim().toLowerCase();

        // Check @ symbol
        if (!upiId.contains("@")) return "❌ Missing @ symbol";

        String[] parts = upiId.split("@");
        if (parts.length != 2) return "❌ Invalid format (multiple @ symbols)";

        String username = parts[0];
        String handle = parts[1];

        // Validate username: 3-50 chars, alphanumeric and dots only
        if (username.length() < 3 || username.length() > 50)
            return "❌ Username must be 3-50 characters";
        if (!username.matches("[a-z0-9.]+"))
            return "❌ Username can only contain lowercase letters, digits, dots";

        // Validate handle against known PSPs
        boolean validHandle = false;
        for (String vh : VALID_HANDLES) {
            if (handle.equals(vh)) { validHandle = true; break; }
        }
        if (!validHandle) return "❌ Unknown handle: @" + handle;

        return "✅ Valid UPI ID → User: " + username + ", PSP: @" + handle;
    }

    public static void main(String[] args) {
        String[] testIds = {
            "rahul.kumar@ybl", "priya@paytm", "amit@unknown",
            "ab@oksbi", "invalid_id", "sneha.reddy@okhdfcbank"
        };
        for (String id : testIds) {
            System.out.printf("%-25s → %s%n", id, validate(id));
        }
    }
}
rahul.kumar@ybl → ✅ Valid UPI ID → User: rahul.kumar, PSP: @ybl priya@paytm → ✅ Valid UPI ID → User: priya, PSP: @paytm amit@unknown → ❌ Unknown handle: @unknown ab@oksbi → ❌ Username must be 3-50 characters invalid_id → ❌ Missing @ symbol sneha.reddy@okhdfcbank → ✅ Valid UPI ID → User: sneha.reddy, PSP: @okhdfcbank
Section D

Learn by Doing — 3-Tier Lab Structure

🟢 Tier 1 — GUIDED TASK: Build a UPI ID Validator Step-by-Step

⏱️ 45–60 minutesBeginnerZero prior knowledge assumed

Step 1: Create the Class

Open your IDE. Create a new file called UPIValidator.java. Type the class skeleton:

Java
public class UPIValidator {
    public static void main(String[] args) {
        String upiId = "rahul.kumar@ybl";
        System.out.println("Testing: " + upiId);
    }
}

Compile and run. You should see: Testing: rahul.kumar@ybl

Step 2: Check for @ Symbol

Java
if (upiId.contains("@")) {
    System.out.println("✅ Contains @ symbol");
} else {
    System.out.println("❌ Missing @ symbol");
}

Step 3: Split Username and Handle

Java
String[] parts = upiId.split("@");
String username = parts[0];
String handle = parts[1];
System.out.println("Username: " + username);
System.out.println("Handle: " + handle);

Step 4: Validate Username Length

Java
if (username.length() >= 3 && username.length() <= 50) {
    System.out.println("✅ Username length OK");
} else {
    System.out.println("❌ Username too short or too long");
}

Step 5: Validate Handle Against Known PSPs

Java
String[] validHandles = {"ybl", "paytm", "oksbi", "okaxis", "ibl"};
boolean found = false;
for (String vh : validHandles) {
    if (handle.equals(vh)) { found = true; break; }
}
System.out.println(found ? "✅ Valid handle" : "❌ Unknown handle");

Step 6: Test with Multiple IDs

Put everything in a method and test with: "priya@paytm", "ab@ybl", "invalid", "amit@unknown"

🎉 Congratulations! You've built a working UPI ID validator using contains(), split(), length(), and equals(). This is exactly what PhonePe's backend does (with more regex and database lookups).

🟡 Tier 2 — SEMI-GUIDED TASK: Text Analytics Tool

⏱️ 60–90 minutesIntermediateHints provided, you fill the gaps

Your Mission:

Build a program that takes a paragraph of text and produces analytics: word count, unique word count, character frequency, sentence count, average word length, and most common word.

Hints:

  1. Word count: Use text.split("\\s+") to split by whitespace. The array length = word count.
  2. Sentence count: Use text.split("[.!?]+"). Count non-empty results.
  3. Character frequency: Use toCharArray() and a loop with an int[26] array for a-z.
  4. Unique words: Use toLowerCase() on each word and track in a HashSet.
  5. Average word length: Sum all word lengths, divide by word count.
Stretch Goal: Add a "readability score" using the formula: 0.39 × (words/sentences) + 11.8 × (syllables/words) − 15.59. Approximate syllables by counting vowels per word.

🔴 Tier 3 — OPEN CHALLENGE: Mini Search Engine

⏱️ 90–120 minutesAdvancedNo instructions — real-world mini-project

The Brief:

Build a mini search engine that searches through an array of article titles and descriptions. Implement:

  1. Exact Match: contains() — find articles containing the exact search term
  2. Case-Insensitive Search: Convert both query and data to toLowerCase()
  3. Multi-Word Search: Split query by spaces, match articles containing ALL words
  4. Search Ranking: Rank results by number of matches (title match = 2 points, description match = 1 point)
  5. Highlight Matches: Use replace() to wrap matched terms in [**...**]
This exact pattern is used in search features of Indian e-commerce apps. Flipkart's product search, Zomato's restaurant search, and Swiggy's menu search all start with String matching before moving to advanced NLP. Build this, and you can add "search engine logic" to your resume.
Section E

Problem Set — Syntax, Programming & Interview Questions

Part 1: Syntax & Tracing (5 Questions)

E1. What is the output?

Java
String s1 = "Java";
String s2 = new String("Java");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
Answer: false then true. s1 is in the pool, s2 is on the heap — different references. But content is the same, so equals() returns true.

E2. What is the output?

Java
String s1 = "Hello";
String s2 = "Hel" + "lo";
String s3 = "Hel";
String s4 = s3 + "lo";
System.out.println(s1 == s2);
System.out.println(s1 == s4);
Answer: true then false. "Hel" + "lo" is a compile-time constant (optimised). s3 + "lo" is runtime concatenation (creates new object).

E3. What is the output?

Java
String s = "Hello";
s.concat(" World");
System.out.println(s);
Answer: Hello. Strings are immutable! concat() returns a NEW String but we never assigned it. The original s is unchanged.

E4. What is the output?

Java
String s = "hello";
s.toUpperCase();
System.out.println(s.charAt(0));
Answer: h (lowercase). toUpperCase() returns a new String, but the return value is not stored. The original s still points to "hello".

E5. What is the output?

Java
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
sb.insert(5, ",");
System.out.println(sb);
Answer: Hello, World. append makes it "Hello World", then insert(5, ",") inserts a comma at position 5 → "Hello, World". StringBuilder is mutable!

Part 2: Programming Questions (8 Questions)

P1. Write a program to reverse a String without using StringBuilder.reverse(). Use a for loop and charAt().

P2. Write a program to count the number of vowels, consonants, digits, and spaces in a given String.

P3. Write a program to remove duplicate characters from a String (e.g., "programming" → "progamin").

P4. Write a program to check if a String is a valid Indian mobile number (starts with 6/7/8/9, exactly 10 digits).

P5. Write a program to find the most frequently occurring character in a String.

P6. Write a program to convert a sentence to Title Case (e.g., "hello world" → "Hello World").

P7. Write a program to compress a String using run-length encoding (e.g., "aaabbbcc" → "a3b3c2").

P8. Write a program that takes a student's name and roll number, then generates an email ID in the format: firstname.rollno@university.edu.

Part 3: Industry Questions (3 Questions)

I1. A Paytm log file contains transaction records in the format: "TXN|timestamp|amount|status|upiId". Write a program to parse 5 such records, calculate total successful transaction amount, and display failed transactions.

I2. You're building a spam filter for an Indian email service. Write a program that checks if an email subject line contains any of these spam keywords: "lottery", "winner", "free", "click here", "urgent". Use toLowerCase() and contains().

I3. An Indian e-commerce site stores product descriptions as pipe-separated values: "name|price|category|rating". Write a program to parse and display products with rating > 4.0, sorted by price.

Part 4: Interview Questions (3 Questions)

🎯 Valid Anagram — Asked at TCS NQT

Problem: Given two strings s and t, return true if t is an anagram of s.

Approach 1 (Sort): Convert both to char arrays, sort, compare. Time: O(n log n).

Approach 2 (Counting): Count character frequencies using int[26]. Increment for s, decrement for t. All counts should be 0. Time: O(n).

🎯 Longest Substring Without Repeating Characters — Asked at Infosys

Problem: Given a string, find the length of the longest substring without repeating characters.

Approach: Sliding window technique. Use a HashSet to track characters in the current window. Expand right; if duplicate found, shrink from left. Track maximum window size.

🎯 String to Integer (atoi) — Asked at Wipro

Problem: Implement your own atoi function that converts a String to an integer. Handle: leading whitespace, +/- sign, overflow, and non-digit characters.

Approach: Use trim(), check sign with charAt(0), iterate digits with charAt(i) - '0', check overflow against Integer.MAX_VALUE.

Section F

MCQ Assessment Bank — 30 Questions (Bloom's Mapped)

Remember / Identify (Q1–Q5)

Q1

Which class in Java is immutable?

  1. StringBuilder
  2. StringBuffer
  3. String
  4. All of the above
Remember
✅ Answer: (C) String — String is immutable. StringBuilder and StringBuffer are mutable.
Q2

What is the default capacity of a StringBuilder object?

  1. 0
  2. 10
  3. 16
  4. 32
Remember
✅ Answer: (C) 16 — The default initial capacity of StringBuilder is 16 characters.
Q3

Which method is used to compare String content in Java?

  1. == operator
  2. equals() method
  3. compare() method
  4. match() method
Remember
✅ Answer: (B) equals() — The == operator compares references, not content. Always use equals() for content comparison.
Q4

Which package contains the String class?

  1. java.util
  2. java.io
  3. java.lang
  4. java.text
Remember
✅ Answer: (C) java.lang — String, StringBuilder, and StringBuffer are all in java.lang (auto-imported).
Q5

What does the charAt(0) method return for the String "Java"?

  1. 'j'
  2. 'J'
  3. 'a'
  4. 74
Remember
✅ Answer: (B) 'J' — charAt(0) returns the first character. Java strings are 0-indexed. The first character of "Java" is uppercase 'J'.

Understand / Explain (Q6–Q10)

Q6

What is the output?
String s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2);

  1. true
  2. false
  3. Compilation error
  4. Runtime exception
Understand
✅ Answer: (A) true — Both are String literals. Java's String pool reuses the same object, so both s1 and s2 point to the same "hello" in the pool.
Q7

What is the output?
String s1 = "hello"; String s2 = new String("hello"); System.out.println(s1 == s2);

  1. true
  2. false
  3. Compilation error
  4. Depends on JVM
Understand
✅ Answer: (B) false — s1 is from the String pool, s2 is a new object on the heap. They are different references even though content is the same.
Q8

Why are Java Strings immutable?

  1. To save disk space
  2. For security, thread-safety, and efficient String pool caching
  3. Because arrays in Java are immutable
  4. To prevent OutOfMemoryError
Understand
✅ Answer: (B) — Immutability enables String pool sharing, makes Strings thread-safe without synchronization, allows hashCode caching, and prevents security issues with passwords and connection strings.
Q9

What is the output?
String s = "Hello"; s.concat(" World"); System.out.println(s);

  1. Hello World
  2. Hello
  3. World
  4. Compilation error
Understand
✅ Answer: (B) Hello — concat() returns a NEW String (since Strings are immutable), but the return value is not assigned to any variable. s still points to "Hello".
Q10

What does "apple".compareTo("banana") return?

  1. 0
  2. A positive number
  3. A negative number
  4. Compilation error
Understand
✅ Answer: (C) A negative number — 'a' (97) minus 'b' (98) = -1. compareTo() returns a negative value when the calling String comes before the argument lexicographically.

Apply / Use (Q11–Q15)

Q11

What is the output?
String s = " Hello World "; System.out.println(s.trim().length());

  1. 15
  2. 11
  3. 13
  4. 12
Apply
✅ Answer: (B) 11 — trim() removes leading and trailing spaces. "Hello World" has 11 characters (including the space between Hello and World).
Q12

What is the output?
String s = "PhonePe@UPI"; String[] parts = s.split("@"); System.out.println(parts[1]);

  1. PhonePe
  2. UPI
  3. @UPI
  4. PhonePe@UPI
Apply
✅ Answer: (B) UPI — split("@") splits at the @ symbol. parts[0] = "PhonePe", parts[1] = "UPI".
Q13

What is the output?
StringBuilder sb = new StringBuilder("Java"); sb.reverse(); System.out.println(sb);

  1. Java
  2. avaJ
  3. jAVA
  4. AVAJ
Apply
✅ Answer: (B) avaJ — reverse() reverses all characters in the StringBuilder. J-a-v-a becomes a-v-a-J.
Q14

What is the output?
String s = "Hello"; System.out.println(s.substring(1, 4));

  1. Hel
  2. ell
  3. ello
  4. Hell
Apply
✅ Answer: (B) ell — substring(1, 4) returns characters from index 1 to 3 (endIndex is exclusive). H(0) e(1) l(2) l(3) o(4) → index 1 to 3 = "ell".
Q15

What is the output?
System.out.println(String.join("-", "2025", "06", "23"));

  1. 2025 06 23
  2. 2025-06-23
  3. -2025-06-23-
  4. 20250623
Apply
✅ Answer: (B) 2025-06-23 — String.join(delimiter, elements...) joins elements with the delimiter between them.

Analyze / Compare (Q16–Q20)

Q16

What is the output?
String s1 = "Hel" + "lo"; String s2 = "Hello"; System.out.println(s1 == s2);

  1. true
  2. false
  3. Compilation error
  4. Depends on JVM version
Analyze
✅ Answer: (A) true — "Hel" + "lo" is a compile-time constant expression. The compiler optimises it to "Hello" at compile time, so it references the same pool object as s2.
Q17

What is the output?
String s1 = "Hel"; String s2 = s1 + "lo"; String s3 = "Hello"; System.out.println(s2 == s3);

  1. true
  2. false
  3. Compilation error
  4. NullPointerException
Analyze
✅ Answer: (B) false — s1 is a variable (not a compile-time constant), so s1 + "lo" is evaluated at runtime, creating a new object on the heap. This is different from the pool reference of s3.
Q18

How many String objects are created by this code?
String s = new String("Hello");

  1. 1
  2. 2
  3. 3
  4. 0
Analyze
✅ Answer: (B) 2 — First, the literal "Hello" is created in the String pool. Then, new String() creates another object on the heap. So 2 objects total (if "Hello" wasn't already in the pool).
Q19

Which is faster for 10,000 concatenations in a loop?

  1. String with + operator
  2. StringBuilder with append()
  3. Both are same speed
  4. StringBuffer with append()
Analyze
✅ Answer: (B) StringBuilder — String + in a loop creates a new object every iteration (O(n²) due to copying). StringBuilder.append() modifies in-place (O(n)). StringBuffer is thread-safe but slower than StringBuilder due to synchronization overhead.
Q20

What is the output?
String s1 = new String("hello"); String s2 = s1.intern(); String s3 = "hello"; System.out.println(s2 == s3);

  1. true
  2. false
  3. Compilation error
  4. Depends on JVM
Analyze
✅ Answer: (A) true — intern() returns the canonical (pool) reference. s3 is also from the pool. Both point to the same pool object, so == returns true.

Evaluate / Justify (Q21–Q25)

Q21

A developer uses String s = "" ; for(int i=0; i<100000; i++) s += i;. What's the main problem?

  1. Syntax error
  2. Creates ~100,000 temporary String objects, causing poor performance and GC pressure
  3. Causes StackOverflowError
  4. No problem, this is efficient
Evaluate
✅ Answer: (B) — Each += creates a new String object, copies all previous content, and discards the old one. For 100,000 iterations, this means O(n²) character copies and ~100,000 garbage objects. Solution: Use StringBuilder.
Q22

When should you use StringBuffer instead of StringBuilder?

  1. When performance is critical
  2. When Strings are small
  3. When multiple threads access the same mutable string simultaneously
  4. Never — StringBuilder is always better
Evaluate
✅ Answer: (C) — StringBuffer's methods are synchronized, making it thread-safe. Use it only when multiple threads modify the same string object. In single-threaded code, always use StringBuilder for better performance.
Q23

Which approach is best for validating an Indian phone number format?

  1. phone.length() == 10 && phone.charAt(0) >= '6'
  2. phone.matches("[6-9][0-9]{9}")
  3. Both are correct but (B) is more readable and maintainable
  4. Neither works
Evaluate
✅ Answer: (C) — Both approaches work. Option A is manual but works. Option B uses regex which is more concise and self-documenting. For complex patterns (email, UPI, PAN card), regex is clearly better.
Q24

What is the output?
final String s1 = "Hel"; String s2 = s1 + "lo"; System.out.println(s2 == "Hello");

  1. true
  2. false
  3. Compilation error
  4. Runtime error
Evaluate
✅ Answer: (A) true — Since s1 is declared final, the compiler treats it as a compile-time constant. So s1 + "lo" becomes "Hel" + "lo" = "Hello" at compile time. This matches the pool reference of "Hello".
Q25

What is the output?
String s1 = "hello"; String s2 = "HELLO"; System.out.println(s1.equals(s2)); System.out.println(s1.equalsIgnoreCase(s2));

  1. true, true
  2. false, true
  3. false, false
  4. true, false
Evaluate
✅ Answer: (B) false, true — equals() is case-sensitive ("hello" ≠ "HELLO"). equalsIgnoreCase() ignores case, so "hello" matches "HELLO".

Create / Design (Q26–Q30)

Q26

Which code correctly checks if a UPI ID contains "@" and the handle is "ybl"?

  1. upi.contains("@") && upi.endsWith("ybl")
  2. upi.split("@")[1].equals("ybl")
  3. upi.indexOf("@ybl") > 0
  4. All of the above could work
Create
✅ Answer: (D) All could work — Option A checks @ presence and ybl suffix. Option B splits and compares the handle. Option C finds "@ybl" substring. All are valid, but B is the most robust (won't match "abcybl").
Q27

What does this code do?
new StringBuilder(str).reverse().toString().equals(str)

  1. Checks if str is an anagram
  2. Checks if str is a palindrome
  3. Reverses str permanently
  4. Causes a compilation error
Create
✅ Answer: (B) Palindrome check — It creates a reversed copy and compares it with the original. If they're equal, the string reads the same forwards and backwards = palindrome.
Q28

Which code counts the occurrences of 'a' in a String?

  1. str.length() - str.replace("a", "").length()
  2. str.split("a").length - 1
  3. str.chars().filter(c -> c == 'a').count()
  4. All of the above
Create
✅ Answer: (D) All work — Option A: difference in length after removing 'a'. Option B: splitting by 'a' creates n+1 parts for n occurrences. Option C: streams API approach. All are clever solutions.
Q29

To build a CSV row from an array of values, which approach is best?

  1. String.join(",", values)
  2. Loop with String concatenation
  3. Loop with StringBuilder
  4. Both A and C are good; A is simpler
Create
✅ Answer: (D) — String.join() is the cleanest one-liner. StringBuilder is also good for complex cases. Avoid loop with String concatenation (creates garbage). In production code, prefer String.join() for readability.
Q30

What is the output?
String s1 = "abc"; String s2 = "abc"; String s3 = new String("abc"); String s4 = s3.intern();
System.out.println(s1 == s2); System.out.println(s1 == s3); System.out.println(s1 == s4);

  1. true, true, true
  2. true, false, true
  3. true, false, false
  4. false, false, true
Create
✅ Answer: (B) true, false, true — s1==s2: both pool references, same object → true. s1==s3: pool vs heap → false. s1==s4: intern() returns pool reference, same as s1 → true. This is the ULTIMATE == vs equals() question!
Section G

Short Answer Questions (8 Questions)

SA1. What is String immutability? Give one advantage and one disadvantage.

Answer: String immutability means once a String object is created, its content cannot be changed. Any operation that seems to modify a String actually creates a new String object.
Advantage: Thread-safety — immutable objects can be shared between threads without synchronization, making concurrent programs safer.
Disadvantage: Performance overhead — repeated string modifications (e.g., concatenation in loops) create many temporary objects, wasting memory and CPU time.

SA2. Explain the String pool with an example.

Answer: The String pool (String Intern Pool) is a special area in Java heap memory where String literals are stored. When you create a String literal like String s1 = "hello", Java checks the pool first. If "hello" exists, s1 gets a reference to the existing object. If not, a new String is created in the pool. Example: String s1 = "hello"; String s2 = "hello"; — both s1 and s2 point to the SAME object. This saves memory by avoiding duplicate String objects.

SA3. Explain the difference between == and equals() for Strings.

Answer: == compares references (whether two variables point to the same object in memory). equals() compares content (whether two Strings contain the same characters). Example: String a = "hello"; String b = new String("hello");a == b is false (different objects), but a.equals(b) is true (same content). Always use equals() for content comparison.

SA4. What is the difference between StringBuilder and StringBuffer?

Answer: Both are mutable (can be modified after creation) and have similar methods (append, insert, delete, reverse). The key difference: StringBuffer is thread-safe (its methods are synchronized), while StringBuilder is not thread-safe but is faster. Use StringBuilder in single-threaded programs (most cases), and StringBuffer only when multiple threads modify the same string simultaneously.

SA5. What does String.format() do? Give an example with format specifiers.

Answer: String.format() creates a formatted string using format specifiers. It works like printf() but returns a String instead of printing. Example: String msg = String.format("Name: %s, Age: %d, CGPA: %.2f", "Rahul", 21, 8.75); produces "Name: Rahul, Age: 21, CGPA: 8.75". Key specifiers: %s (string), %d (integer), %f (float), %c (char), %b (boolean).

SA6. What does the intern() method do?

Answer: The intern() method returns a canonical representation of a String from the String pool. If a String with the same content already exists in the pool, it returns a reference to the pool copy. If not, the string is added to the pool. Example: String s1 = new String("hello").intern(); — s1 now points to the pool version of "hello", making s1 == "hello" return true.

SA7. Why is the String class declared final in Java?

Answer: The String class is declared final to prevent subclassing (inheritance). If someone could create a subclass of String and override methods like equals() or hashCode(), it would break: (1) Security — passwords and connection strings could be manipulated, (2) String pool integrity — the pool relies on immutability guaranteed by the String class, (3) Hash-based collections — HashMap/HashSet depend on consistent String behavior.

SA8. What is the use of toCharArray()? Give a practical example.

Answer: toCharArray() converts a String into a char[] array. This is useful for: (1) Character-by-character processing, (2) Sorting characters (for anagram detection), (3) In-place modifications. Practical example — checking anagrams: char[] arr1 = s1.toCharArray(); char[] arr2 = s2.toCharArray(); Arrays.sort(arr1); Arrays.sort(arr2); return Arrays.equals(arr1, arr2);
Section H

Long Answer Questions (3 Questions)

LA1. Explain String immutability with a memory diagram. Discuss advantages and disadvantages of immutability. (10 marks)

Answer:

Definition: In Java, once a String object is created, its value (the character sequence) can never be changed. The String class is declared final, and its internal char[] (or byte[] since Java 9) is private and final.

Memory Diagram:

String s1 = "Hello";   // Creates "Hello" in String pool
String s2 = s1;        // s2 points to same "Hello"
s1 = s1 + " World";   // Creates NEW "Hello World", s1 re-pointed

BEFORE s1 = s1 + " World":
  s1 ──→ "Hello" ←── s2    (same object in pool)

AFTER s1 = s1 + " World":
  s1 ──→ "Hello World"     (new object on heap)
  s2 ──→ "Hello"            (still points to original)

Advantages: (1) Thread-safety without synchronization, (2) Safe for use as HashMap keys (hashCode is cached), (3) String pool saves memory, (4) Security for sensitive data like passwords, (5) Class loading uses Strings — immutability prevents tampering.

Disadvantages: (1) Performance overhead for frequent modifications, (2) Memory waste with concatenation in loops, (3) Extra GC pressure from temporary String objects.

Solution: Use StringBuilder for mutable operations.

LA2. Compare String, StringBuilder, and StringBuffer with code examples and performance analysis. (10 marks)

Answer:

String (Immutable): Every modification creates a new object.

String s = "Hello";
s = s + " World";  // New object created, old "Hello" is garbage

StringBuilder (Mutable, Not Thread-Safe): Modifies in-place. Best for single-threaded use.

StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");  // Same object modified

StringBuffer (Mutable, Thread-Safe): Like StringBuilder but synchronized. Use only for multi-threaded access.

StringBuffer sbuf = new StringBuffer("Hello");
sbuf.append(" World");  // Thread-safe modification

Performance Comparison (10,000 concatenations): String: ~450ms, StringBuilder: ~1ms, StringBuffer: ~3ms. StringBuilder is ~450× faster than String and ~3× faster than StringBuffer for single-threaded use.

When to Use: String — when content won't change, for constants, map keys. StringBuilder — single-threaded string building, loops, dynamic queries. StringBuffer — shared mutable strings in multi-threaded applications (rare in modern Java, prefer StringBuilder + external synchronization).

LA3. Write and explain a complete program that processes student data stored as CSV strings. Include parsing, validation, and formatted output. (10 marks)

Answer:
public class StudentCSVProcessor {
    public static void main(String[] args) {
        String[] records = {
            "101,Rahul Sharma,BCA,8.5,Mumbai",
            "102,Priya Patel,B.Tech,9.2,Ahmedabad",
            "103,,MCA,7.0,Delhi",              // Missing name
            "104,Amit Kumar,BCA,invalid,Pune"   // Invalid CGPA
        };

        StringBuilder report = new StringBuilder();
        report.append(String.format("%-6s %-20s %-8s %-6s %-12s%n",
                "ROLL", "NAME", "COURSE", "CGPA", "CITY"));
        report.append("─".repeat(55)).append("\n");

        int valid = 0, invalid = 0;
        double totalCgpa = 0;

        for (String record : records) {
            String[] fields = record.split(",");
            if (fields.length != 5) { invalid++; continue; }

            String roll = fields[0].trim();
            String name = fields[1].trim();
            String course = fields[2].trim();
            String cgpaStr = fields[3].trim();
            String city = fields[4].trim();

            // Validate name
            if (name.isEmpty()) {
                report.append("⚠️ Record " + roll + ": Missing name\n");
                invalid++; continue;
            }

            // Validate CGPA
            double cgpa;
            try {
                cgpa = Double.parseDouble(cgpaStr);
            } catch (NumberFormatException e) {
                report.append("⚠️ Record " + roll + ": Invalid CGPA\n");
                invalid++; continue;
            }

            report.append(String.format("%-6s %-20s %-8s %-6.1f %-12s%n",
                    roll, name, course, cgpa, city));
            totalCgpa += cgpa;
            valid++;
        }

        report.append("─".repeat(55)).append("\n");
        report.append("Valid: " + valid + " | Invalid: " + invalid);
        if (valid > 0)
            report.append(" | Avg CGPA: " +
                String.format("%.2f", totalCgpa / valid));

        System.out.println(report);
    }
}

Explanation: The program uses split(",") to parse CSV fields, trim() to clean whitespace, isEmpty() for validation, try-catch for CGPA parsing, String.format() for aligned output, and StringBuilder for efficient report building. This mirrors real-world data processing at companies like TCS and Infosys.

Section I

Lab Program — Lab 6: String and StringBuilder

🔬 Lab 6: String & StringBuilder — Complete Methods & Mutability Comparison

⏱️ 90–120 minutesIntermediateAll major methods + performance test

Aim:

To demonstrate all major String and StringBuilder methods, understand immutability vs mutability, and compare performance of String concatenation vs StringBuilder.

Complete Code:

Java
public class Lab6_StringAndStringBuilder {

    public static void main(String[] args) {

        // ═══════════════════════════════════════
        // PART 1: String Creation — Literal vs new
        // ═══════════════════════════════════════
        System.out.println("══ PART 1: String Creation ══");
        String s1 = "Hello";             // String pool
        String s2 = "Hello";             // Same pool reference
        String s3 = new String("Hello"); // Heap (new object)

        System.out.println("s1 == s2 (pool): " + (s1 == s2));       // true
        System.out.println("s1 == s3 (new):  " + (s1 == s3));       // false
        System.out.println("s1.equals(s3):   " + s1.equals(s3));    // true

        // ═══════════════════════════════════════
        // PART 2: All Major String Methods
        // ═══════════════════════════════════════
        System.out.println("\n══ PART 2: String Methods ══");
        String str = "  Programming in Java  ";

        System.out.println("Original:      '" + str + "'");
        System.out.println("length():      " + str.length());
        System.out.println("trim():        '" + str.trim() + "'");
        System.out.println("toUpperCase(): " + str.trim().toUpperCase());
        System.out.println("toLowerCase(): " + str.trim().toLowerCase());
        System.out.println("charAt(2):     " + str.trim().charAt(2));
        System.out.println("indexOf('Java'):" + str.indexOf("Java"));
        System.out.println("contains('Java'):" + str.contains("Java"));
        System.out.println("startsWith('  P'):" + str.startsWith("  P"));
        System.out.println("endsWith('a  '):" + str.endsWith("a  "));
        System.out.println("substring(2,13):" + str.substring(2, 13));
        System.out.println("replace:       " + str.trim().replace("Java", "Python"));
        System.out.println("isEmpty():     " + str.isEmpty());
        System.out.println("isEmpty(''):   " + "".isEmpty());

        // split and join
        String csv = "Rahul,BCA,Mumbai,8.5";
        String[] parts = csv.split(",");
        System.out.println("\nCSV split: " + csv);
        for (int i = 0; i < parts.length; i++)
            System.out.println("  Field " + i + ": " + parts[i]);
        System.out.println("join:      " + String.join(" | ", parts));

        // compareTo
        System.out.println("\ncompareTo('Apple','Banana'): " + "Apple".compareTo("Banana"));
        System.out.println("compareTo('Cat','Cat'):     " + "Cat".compareTo("Cat"));
        System.out.println("equalsIgnoreCase:           " + "java".equalsIgnoreCase("JAVA"));

        // valueOf and format
        System.out.println("\nvalueOf(42):  " + String.valueOf(42));
        System.out.println("format:       " + String.format("₹%,.2f", 1500.5));

        // ═══════════════════════════════════════
        // PART 3: StringBuilder Operations
        // ═══════════════════════════════════════
        System.out.println("\n══ PART 3: StringBuilder ══");
        StringBuilder sb = new StringBuilder("Hello");

        System.out.println("Initial:    " + sb);
        System.out.println("capacity(): " + sb.capacity());
        System.out.println("length():   " + sb.length());

        sb.append(" World");
        System.out.println("append:     " + sb);

        sb.insert(5, ",");
        System.out.println("insert:     " + sb);

        sb.replace(7, 12, "India");
        System.out.println("replace:    " + sb);

        sb.delete(5, 6);
        System.out.println("delete:     " + sb);

        sb.reverse();
        System.out.println("reverse:    " + sb);

        sb.reverse();  // Reverse back
        sb.setCharAt(0, 'h');
        System.out.println("setCharAt:  " + sb);

        System.out.println("toString(): " + sb.toString());

        // ═══════════════════════════════════════
        // PART 4: Immutability vs Mutability Proof
        // ═══════════════════════════════════════
        System.out.println("\n══ PART 4: Mutability Comparison ══");

        // String — immutable
        String original = "Hello";
        String modified = original.concat(" World");
        System.out.println("String original after concat: " + original);  // Still "Hello"
        System.out.println("String modified:              " + modified); // "Hello World"

        // StringBuilder — mutable
        StringBuilder sbOrig = new StringBuilder("Hello");
        sbOrig.append(" World");
        System.out.println("StringBuilder after append:    " + sbOrig);   // "Hello World" — changed!

        // ═══════════════════════════════════════
        // PART 5: Performance Comparison
        // ═══════════════════════════════════════
        System.out.println("\n══ PART 5: Performance Test ══");
        int iterations = 50000;

        // String concatenation
        long start = System.currentTimeMillis();
        String strConcat = "";
        for (int i = 0; i < iterations; i++) {
            strConcat = strConcat + "a";
        }
        long stringTime = System.currentTimeMillis() - start;

        // StringBuilder
        start = System.currentTimeMillis();
        StringBuilder sbConcat = new StringBuilder();
        for (int i = 0; i < iterations; i++) {
            sbConcat.append("a");
        }
        String sbResult = sbConcat.toString();
        long sbTime = System.currentTimeMillis() - start;

        System.out.println("String concat (" + iterations + " iterations): " + stringTime + " ms");
        System.out.println("StringBuilder (" + iterations + " iterations): " + sbTime + " ms");
        System.out.println("StringBuilder is ~" + (stringTime / Math.max(sbTime, 1)) + "x faster!");

        System.out.println("\n✅ Lab 6 Complete!");
    }
}

Expected Output:

══ PART 1: String Creation ══ s1 == s2 (pool): true s1 == s3 (new): false s1.equals(s3): true ══ PART 2: String Methods ══ Original: ' Programming in Java ' length(): 23 trim(): 'Programming in Java' toUpperCase(): PROGRAMMING IN JAVA toLowerCase(): programming in java charAt(2): o indexOf('Java'):17 contains('Java'):true startsWith(' P'):true endsWith('a '):true substring(2,13):Programming replace: Programming in Python isEmpty(): false isEmpty(''): true CSV split: Rahul,BCA,Mumbai,8.5 Field 0: Rahul Field 1: BCA Field 2: Mumbai Field 3: 8.5 join: Rahul | BCA | Mumbai | 8.5 compareTo('Apple','Banana'): -1 compareTo('Cat','Cat'): 0 equalsIgnoreCase: true valueOf(42): 42 format: ₹1,500.50 ══ PART 3: StringBuilder ══ Initial: Hello capacity(): 21 length(): 5 append: Hello World insert: Hello, World replace: Hello, India delete: Hello India reverse: aidnI olleH setCharAt: hello India toString(): hello India ══ PART 4: Mutability Comparison ══ String original after concat: Hello String modified: Hello World StringBuilder after append: Hello World ══ PART 5: Performance Test ══ String concat (50000 iterations): 1842 ms StringBuilder (50000 iterations): 2 ms StringBuilder is ~921x faster! ✅ Lab 6 Complete!

📋 Viva Questions & Answers:

V1. Why does s1 == s2 return true but s1 == s3 return false?

Both s1 and s2 are String literals. Java's String pool ensures only one copy of "Hello" exists, so both variables point to the same object. s3 uses new String() which forces creation of a separate object on the heap, even though the content is identical.

V2. What happens to the original String when we call concat()?

Nothing — the original String remains unchanged because Strings are immutable. concat() creates and returns a new String with the appended content. If the return value isn't assigned to a variable, the new String is immediately eligible for garbage collection.

V3. Why is StringBuilder so much faster than String for concatenation in loops?

String concatenation with + in a loop creates a new String object on every iteration, copying all previous characters each time. This results in O(n²) character copies for n iterations. StringBuilder modifies its internal character array in-place with append(), resulting in O(n) operations total. No intermediate garbage objects are created.

V4. What is the initial capacity of new StringBuilder("Hello") and why?

The capacity is 21 (= 16 + 5). The default capacity is 16, and "Hello" has 5 characters. When initialised with a String, the capacity = 16 + string length. This provides room for growth without immediate array resizing.

V5. Can we use == after calling intern()? Why?

Yes. intern() returns a reference from the String pool. If two Strings have the same content and both are interned (or one is a literal), == will return true because they point to the same pool object. Example: "hello" == new String("hello").intern() is true.

🔧 Extension Exercise:

Extend Lab 6 by adding Part 6: "String Encryption". Implement a simple Caesar cipher that shifts each character by a given key. Use charAt(), StringBuilder.append(), and character arithmetic. Test with: encrypt("HELLO", 3) → "KHOOR" and decrypt("KHOOR", 3) → "HELLO".
Section J

Industry Spotlight — A Day in the Life

👨‍💻 Amit Kumar, 26 — Java Backend Developer at Paytm, Noida

Background: B.Tech from a Tier-3 engineering college in Bihar. No connections in the tech industry. Self-taught Java during 2nd year using YouTube (Telusko, Durga Soft). Built 3 projects on GitHub — a UPI payment simulator, a text-based invoice generator, and a CSV-to-JSON converter. Got placed at Paytm through an off-campus drive via LinkedIn.

A Typical Day:

9:00 AM — Standup with the Payments Platform team. Review yesterday's transaction processing metrics.

9:30 AM — Work on a Jira ticket: "Improve UPI ID validation logic." Uses String methods — contains(), split(), matches() with regex to validate UPI formats.

11:00 AM — Debug a production issue: payment receipts showing garbled text. Root cause: String encoding mismatch (UTF-8 vs ISO-8859-1). Fix using new String(bytes, StandardCharsets.UTF_8).

12:30 PM — Lunch at Paytm campus cafeteria. Discuss upcoming feature: masked UPI IDs in transaction history (e.g., "ra***@ybl").

1:30 PM — Implement the masking feature: upiId.substring(0, 2) + "***" + upiId.substring(upiId.indexOf("@")). Uses StringBuilder for batch processing 100K+ records.

3:30 PM — Write JUnit tests for the masking logic. Test edge cases: short usernames, missing @, special characters.

5:00 PM — Code review a colleague's PR. Spot a performance issue: String concatenation in a loop processing 50K transactions. Suggest StringBuilder. Estimated savings: 200ms per batch.

6:00 PM — Learning hour: studying Java Streams and regex patterns for the next sprint's text analytics feature.

DetailInfo
Tools Used DailyJava (Spring Boot), String/StringBuilder extensively, IntelliJ IDEA, Git, Kafka, MySQL
Entry Salary (2024)₹5–8 LPA + benefits
Mid-Level (3–5 yrs)₹12–20 LPA
Senior (7+ yrs)₹25–45 LPA
Companies Hiring Java DevsPaytm, PhonePe, Razorpay, Flipkart, Amazon, Goldman Sachs, TCS, Infosys, Wipro, HCL, Oracle, Samsung
Amit's advice for students: "Don't wait for placements. Start building projects with String processing — invoice generators, data parsers, form validators. Put them on GitHub. I got 3 interview calls from LinkedIn just because recruiters saw my CSV parser project. Java String skills are asked in EVERY interview — TCS NQT, Infosys InfyTQ, Wipro NLTH. Master == vs equals(), and you'll clear 90% of MCQ rounds."
Section K

Earn With It — Freelance & Income Roadmap

💰 Your Earning Path After This Chapter

Portfolio Piece: "UPI ID Validator + CSV Data Processor" — a Java console application demonstrating String/StringBuilder mastery, input validation, and formatted output.

Text Processing Script Gig Ideas:

• CSV file cleaner/formatter for small businesses — ₹2,000–₹5,000

• Data validation script (email, phone, PAN, Aadhaar format) — ₹3,000–₹8,000

• Text-to-report converter (raw data → formatted invoices) — ₹5,000–₹12,000

• Log file parser and analytics generator — ₹4,000–₹10,000

• Bulk SMS/email template generator from CSV contact list — ₹2,000–₹6,000

PlatformBest ForTypical Rate
InternshalaIndian student internships & Java projects₹3,000–₹10,000/project
FiverrGlobal clients, text processing scripts$15–$60/gig (₹1,200–₹5,000)
UpworkLonger Java development projects$15–$35/hour
LinkedInDirect outreach to Indian startups₹5,000–₹15,000/project
GitHubOpen-source contributions → job referralsIndirect (portfolio building)

⏱️ Time to First Earning: 2–4 weeks (build 2 text processing tools, create a Fiverr gig, share on LinkedIn)

Quick win: Many Indian coaching centres, schools, and small businesses have messy CSV/Excel data. Offer to write a Java program that cleans and formats their data automatically. Charge ₹3,000–₹5,000 for a script that saves them hours of manual work. This is a real-world application of split(), trim(), replace(), and String.format().
Section L

Chapter Summary & Code Tweet

📝 Key Takeaways from Unit 7

String is immutable — every "modification" creates a new object. Use String pool for memory efficiency.

String pool reuses literal Strings — "hello" == "hello" is true. new String("hello") creates a separate heap object.

NEVER use == for content comparison — use equals() or equalsIgnoreCase(). This is the #1 Java interview question.

compareTo() returns negative/zero/positive for lexicographic ordering. Used for sorting Strings.

Key String methods: length(), charAt(), substring(), indexOf(), contains(), split(), join(), trim(), replace(), toUpperCase(), toLowerCase(), format(), valueOf(), startsWith(), endsWith(), isEmpty(), toCharArray().

StringBuilder is mutable — use it for frequent modifications, especially in loops. Methods: append(), insert(), delete(), reverse(), replace(), capacity(), setCharAt().

StringBuilder vs StringBuffer: Same methods, but StringBuffer is thread-safe (synchronized). Prefer StringBuilder in single-threaded code.

String.format()/printf(): Format specifiers %s, %d, %f, %c for creating formatted output.

Real-world usage: UPI ID validation, CSV parsing, text analytics, log processing — all built on String methods.

🐦 Code Tweet — The Entire Chapter in One Snippet

Java
// Unit 7 in 7 lines 🚀
String s = "hello";                      // Pool ✓
boolean b = s.equals(new String("hello")); // true (use this, not ==)
String[] parts = "a@b".split("@");      // ["a","b"]
String up = s.toUpperCase();               // "HELLO" (new String!)
StringBuilder sb = new StringBuilder(s);  // Mutable 🔥
sb.append(" world").reverse();            // "dlrow olleh"
System.out.printf("₹%,.2f%n", 1500.5);  // ₹1,500.50
Section M

Earning Checkpoint — What You Can Do Now

TopicTool/MethodPortfolio PieceEarning Ready?
String ImmutabilityConceptual + == vs equals()✅ Yes — interview knowledge
String Methodssplit, trim, replace, format, containsUPI ID Validator✅ Yes — text processing scripts
StringBuilderappend, reverse, insert, deletePerformance Comparison Tool✅ Yes — optimised data processing
CSV Parsingsplit, trim, formatStudent CSV Processor✅ Yes — ₹3K–₹8K/project
String Formattingprintf, String.formatInvoice/Receipt Generator✅ Yes — billing tools for local shops
Palindrome/Anagramreverse, sort, toCharArrayInterview Practice Suite✅ Yes — DSA interview prep
Input Validationmatches, contains, startsWithForm Validator (UPI, Phone, Email)✅ Yes — web form backend scripts
Minimum Viable Earning Setup after this chapter: A GitHub profile with 2–3 text processing Java projects (UPI validator, CSV parser, text analytics) + an Internshala/Fiverr profile with a clear gig description = you can earn ₹5,000–₹20,000/month from Java scripting gigs while still in college.

✅ Unit 7 complete. MCQs: 30. Lab 6 covered. Ready for Unit 8!

[QR: Link to EduArtha video tutorial — Java Strings & StringBuilder]