Master Java arrays including multi-dimensional arrays and the Arrays utility class, and gain deep understanding of String immutability, StringBuilder, and the 20 most commonly used String methods.
Arrays and strings are the two most fundamental data structures you use in every Java program. Arrays provide fixed-size, ordered, indexed storage of elements of the same type — the backbone of algorithms, matrix computations, and buffer management. Strings represent text and are everywhere: HTTP headers, database values, user input, log messages, and API responses.
Java's String class has a critical design property that surprises newcomers: strings are immutable. Every operation that appears to modify a string actually creates a new String object. This design enables the string pool (memory sharing), safe use as HashMap keys, and thread safety, but it means naive string concatenation in a loop creates O(n) objects and destroys performance. StringBuilder solves this. In this lesson you will understand both the array memory model and the string immutability model, and learn the most practically useful methods for each.
1// Declaration + allocation (elements initialized to 0/null/false)
2int[] numbers = new int[5]; // {0, 0, 0, 0, 0}
3String[] names = new String[3]; // {null, null, null}
4
5// Declaration + initialization (array literal)
6int[] primes = {2, 3, 5, 7, 11};
7String[] colors = {"red", "green", "blue"};
8
9// Access by index (zero-based)
10System.out.println(primes[0]); // 2
11System.out.println(primes[4]); // 11
12// primes[5]; // ArrayIndexOutOfBoundsException at runtime
13
14// Length property (not a method!)
15System.out.println(primes.length); // 5
16
17// Iterate with for loop (when index is needed)
18for (int i = 0; i < primes.length; i++) {
19 System.out.printf("primes[%d] = %d%n", i, primes[i]);
20}
21
22// Iterate with enhanced for (when index not needed)
23for (int prime : primes) {
24 System.out.println(prime);
25}
26
27// Array references — assignment copies the reference, not the data
28int[] a = {1, 2, 3};
29int[] b = a; // b points to the same array
30b[0] = 99;
31System.out.println(a[0]); // 99 — a was modified through b!
32
33// To copy: use Arrays.copyOf or System.arraycopy
34int[] c = Arrays.copyOf(a, a.length); // independent copy
35c[0] = 0;
36System.out.println(a[0]); // 99 — a unchanged1// 2D array (array of arrays)
2int[][] matrix = new int[3][4]; // 3 rows, 4 columns
3
4// Initialize with values
5int[][] grid = {
6 {1, 2, 3},
7 {4, 5, 6},
8 {7, 8, 9}
9};
10
11// Access: [row][column]
12System.out.println(grid[1][2]); // 6 (row 1, column 2)
13
14// Iterate 2D array
15for (int row = 0; row < grid.length; row++) {
16 for (int col = 0; col < grid[row].length; col++) {
17 System.out.printf("%3d", grid[row][col]);
18 }
19 System.out.println();
20}
21
22// Jagged arrays: rows of different lengths
23int[][] triangle = new int[4][];
24for (int i = 0; i < triangle.length; i++) {
25 triangle[i] = new int[i + 1];
26}
27// triangle[0] has 1 element, [1] has 2, [2] has 3, [3] has 4
28
29// java.util.Arrays utility class
30import java.util.Arrays;
31
32int[] nums = {5, 2, 8, 1, 9, 3};
33
34Arrays.sort(nums); // in-place sort: {1, 2, 3, 5, 8, 9}
35int idx = Arrays.binarySearch(nums, 8); // 4 — index after sort
36System.out.println(Arrays.toString(nums)); // [1, 2, 3, 5, 8, 9]
37
38int[] copy = Arrays.copyOf(nums, 3); // first 3 elements: [1, 2, 3]
39int[] ext = Arrays.copyOf(nums, 8); // extended with 0s: [1,2,3,5,8,9,0,0]
40int[] range = Arrays.copyOfRange(nums, 2, 5); // [3, 5, 8]
41
42Arrays.fill(copy, 0); // {0, 0, 0}
43
44// Compare arrays by content
45int[] x = {1, 2, 3};
46int[] y = {1, 2, 3};
47System.out.println(x == y); // false — reference equality
48System.out.println(Arrays.equals(x, y)); // true — content equality
49
50// Sort with custom comparator (requires Integer[] not int[])
51Integer[] words = {5, 2, 8, 1};
52Arrays.sort(words, (a, b) -> b - a); // sort descending
53System.out.println(Arrays.toString(words)); // [8, 5, 2, 1]1// Strings are IMMUTABLE — every "modification" creates a NEW object
2String s = "hello";
3String upper = s.toUpperCase(); // new String object
4System.out.println(s); // "hello" — unchanged
5System.out.println(upper); // "HELLO" — new object
6
7// String pool: literals are interned (shared in heap)
8String a = "hello";
9String b = "hello";
10System.out.println(a == b); // true — same pool object
11System.out.println(a.equals(b)); // true — same content
12
13String c = new String("hello"); // forces new heap object
14System.out.println(a == c); // false — different reference
15System.out.println(a.equals(c)); // true — same content
16
17// ALWAYS use .equals() for String comparison
18String userInput = getInput();
19if ("admin".equals(userInput)) { ... } // null-safe form (literal first)
20if (Objects.equals(userInput, "admin")) { ... } // both null-safe
21
22// Concatenation creates new objects — bad in loops!
23String result = "";
24for (int i = 0; i < 1000; i++) {
25 result += i; // creates 1000 intermediate String objects!
26}
27
28// String.intern() forces pooling of runtime strings
29String s1 = new String("hello").intern();
30String s2 = "hello";
31System.out.println(s1 == s2); // true — both from pool1// StringBuilder: mutable, not thread-safe, fast
2StringBuilder sb = new StringBuilder();
3sb.append("Hello");
4sb.append(", ");
5sb.append("World");
6sb.append('!');
7System.out.println(sb.toString()); // "Hello, World!"
8
9// Method chaining (append returns 'this')
10String result = new StringBuilder()
11 .append("Name: ")
12 .append("Alice")
13 .append(", Age: ")
14 .append(25)
15 .toString();
16
17// StringBuilder operations
18StringBuilder sb2 = new StringBuilder("Hello World");
19sb2.insert(5, ","); // "Hello, World"
20sb2.delete(5, 6); // "Hello World"
21sb2.replace(6, 11, "Java"); // "Hello Java"
22sb2.reverse(); // "avaJ olleH"
23System.out.println(sb2.length()); // current length
24System.out.println(sb2.charAt(0)); // 'a'
25
26// Performance comparison
27long start = System.nanoTime();
28String s = "";
29for (int i = 0; i < 100_000; i++) s += i; // slow: O(n²)
30System.out.printf("Concatenation: %d ms%n",
31 (System.nanoTime() - start) / 1_000_000);
32
33start = System.nanoTime();
34StringBuilder sb3 = new StringBuilder();
35for (int i = 0; i < 100_000; i++) sb3.append(i); // fast: O(n)
36System.out.printf("StringBuilder: %d ms%n",
37 (System.nanoTime() - start) / 1_000_000);
38
39// Use String.join for delimited lists
40String csv = String.join(", ", "Alice", "Bob", "Charlie");
41System.out.println(csv); // "Alice, Bob, Charlie"
42
43List<String> parts = List.of("one", "two", "three");
44String joined = String.join(" | ", parts);
45System.out.println(joined); // "one | two | three"1String s = " Hello, World! ";
2
3// Length and case
4System.out.println(s.length()); // 18
5System.out.println(s.toUpperCase()); // " HELLO, WORLD! "
6System.out.println(s.toLowerCase()); // " hello, world! "
7
8// Trimming whitespace
9System.out.println(s.trim()); // "Hello, World!" (removes leading/trailing)
10System.out.println(s.strip()); // "Hello, World!" (Unicode-aware, Java 11+)
11System.out.println(s.stripLeading()); // "Hello, World! "
12System.out.println(s.stripTrailing()); // " Hello, World!"
13
14// Searching
15String t = "Hello, World!";
16System.out.println(t.indexOf('o')); // 4
17System.out.println(t.indexOf('o', 5)); // 8 (start from index 5)
18System.out.println(t.lastIndexOf('o')); // 8
19System.out.println(t.contains("World")); // true
20System.out.println(t.startsWith("Hello")); // true
21System.out.println(t.endsWith("!")); // true
22System.out.println(t.isEmpty()); // false
23System.out.println("".isBlank()); // true (Java 11+)
24System.out.println(" ".isBlank()); // true
25
26// Extracting substrings
27System.out.println(t.substring(7)); // "World!"
28System.out.println(t.substring(7, 12)); // "World"
29System.out.println(t.charAt(0)); // 'H'
30
31// Replacing
32System.out.println(t.replace('l', 'L')); // "HeLLo, WorLd!"
33System.out.println(t.replace("World", "Java")); // "Hello, Java!"
34System.out.println(t.replaceAll("[aeiou]", "*")); // regex replace
35System.out.println(t.replaceFirst("[A-Z]", "X"));// replace first match
36
37// Splitting
38String csv = "Alice,Bob,Charlie,Diana";
39String[] parts = csv.split(",");
40System.out.println(parts.length); // 4
41System.out.println(parts[0]); // "Alice"
42
43// Limit: split at most N times
44String[] first2 = csv.split(",", 2); // {"Alice", "Bob,Charlie,Diana"}
45
46// Formatting
47String formatted = String.format("Name: %s, Age: %d, Score: %.2f",
48 "Alice", 25, 98.5);
49System.out.println(formatted); // "Name: Alice, Age: 25, Score: 98.50"
50
51// Text blocks (Java 15+) — multiline strings
52String json = """
53 {
54 "name": "Alice",
55 "age": 25
56 }
57 """;
58System.out.println(json);
59
60// Comparison
61System.out.println("apple".compareTo("banana")); // negative (a < b)
62System.out.println("apple".compareToIgnoreCase("APPLE")); // 0
63System.out.println("abc".equalsIgnoreCase("ABC")); // trueA complete program that parses CSV data using String methods, stores results in arrays, sorts them, and generates a formatted report using StringBuilder.
1import java.util.Arrays;
2
3/**
4 * CsvProcessor.java
5 * Parses a CSV string of student records, computes statistics,
6 * and generates a formatted report using arrays and String manipulation.
7 */
8public class CsvProcessor {
9
10 static final String CSV_DATA =
11 "Alice,92,85,88\n" +
12 "Bob,74,68,72\n" +
13 "Charlie,88,91,95\n" +
14 "Diana,55,60,58\n" +
15 "Eve,97,99,98\n" +
16 "Frank,63,70,65";
17
18 public static void main(String[] args) {
19 String[] lines = CSV_DATA.split("\n");
20 int studentCount = lines.length;
21
22 // Parse data into parallel arrays
23 String[] names = new String[studentCount];
24 double[] averages = new double[studentCount];
25
26 for (int i = 0; i < studentCount; i++) {
27 String[] fields = lines[i].trim().split(",");
28
29 names[i] = fields[0].trim();
30
31 // Parse scores (fields[1] through end)
32 int sum = 0;
33 for (int j = 1; j < fields.length; j++) {
34 sum += Integer.parseInt(fields[j].trim());
35 }
36 averages[i] = (double) sum / (fields.length - 1);
37 }
38
39 printOriginalReport(names, averages);
40 printSortedReport(names, averages);
41 printSummary(averages);
42 printGradeLetters(names, averages);
43 }
44
45 static void printOriginalReport(String[] names, double[] averages) {
46 System.out.println("=== Student Report (Original Order) ===");
47 System.out.printf("%-12s %8s %6s%n", "Name", "Average", "Grade");
48 System.out.println("-".repeat(30));
49
50 for (int i = 0; i < names.length; i++) {
51 String grade = getGrade(averages[i]);
52 System.out.printf("%-12s %8.2f %6s%n",
53 names[i], averages[i], grade);
54 }
55 }
56
57 static void printSortedReport(String[] names, double[] averages) {
58 // Create index array for sorting without modifying originals
59 Integer[] indices = new Integer[names.length];
60 for (int i = 0; i < indices.length; i++) indices[i] = i;
61
62 // Sort indices by average (descending)
63 Arrays.sort(indices, (a, b) -> Double.compare(averages[b], averages[a]));
64
65 System.out.println("\n=== Student Ranking (Highest to Lowest) ===");
66 for (int rank = 0; rank < indices.length; rank++) {
67 int idx = indices[rank];
68 System.out.printf("Rank %d: %-12s %.2f (%s)%n",
69 rank + 1, names[idx], averages[idx], getGrade(averages[idx]));
70 }
71 }
72
73 static void printSummary(double[] averages) {
74 double sum = 0, min = averages[0], max = averages[0];
75 for (double avg : averages) {
76 sum += avg;
77 if (avg < min) min = avg;
78 if (avg > max) max = avg;
79 }
80
81 System.out.println("\n=== Class Statistics ===");
82 System.out.printf("Class average : %.2f%n", sum / averages.length);
83 System.out.printf("Highest score : %.2f%n", max);
84 System.out.printf("Lowest score : %.2f%n", min);
85 }
86
87 static void printGradeLetters(String[] names, double[] averages) {
88 // Build summary string using StringBuilder
89 StringBuilder sb = new StringBuilder();
90 sb.append("\n=== Grade Summary ===\n");
91
92 for (int i = 0; i < names.length; i++) {
93 String grade = getGrade(averages[i]);
94 String paddedName = padRight(names[i], 10);
95 sb.append(paddedName)
96 .append(": ")
97 .append(grade)
98 .append("\n");
99 }
100
101 System.out.print(sb.toString());
102 }
103
104 static String getGrade(double avg) {
105 if (avg >= 90) return "A";
106 else if (avg >= 80) return "B";
107 else if (avg >= 70) return "C";
108 else if (avg >= 60) return "D";
109 else return "F";
110 }
111
112 // Pad string to fixed width (manual implementation for demonstration)
113 static String padRight(String s, int width) {
114 if (s.length() >= width) return s;
115 StringBuilder sb = new StringBuilder(s);
116 while (sb.length() < width) sb.append(' ');
117 return sb.toString();
118 }
119}This program demonstrates: CSV parsing with split(), trim() to clean whitespace, Integer.parseInt() for type conversion, parallel arrays for student data, sorting with a custom Comparator lambda on index arrays (to preserve the original data), StringBuilder for building the summary report, printf formatting with %-12s for left-aligned fixed-width columns, and a helper method that uses switch logic for grade calculation. The index-sort pattern (sort an array of indices rather than the data) is a common technique when you need to sort related parallel arrays together.
With arrays and strings mastered, the next lesson introduces Object-Oriented Programming: defining classes, creating objects with constructors, encapsulating state with private fields and public methods, and using the this keyword. OOP is the core paradigm of Java and the foundation for all frameworks you will use professionally.
Your progress is saved in this browser, on this device only.