Index

Data Structures Arrays and Strings

Java for Beginners

5.1 One-Dimensional and Multidimensional Arrays

In programming, it's common to work with collections of related data. An array is one of the most basic and useful data structures for storing multiple values of the same type in a single, organized place.

In this section, we’ll introduce one-dimensional arrays and then extend to multidimensional arrays, especially two-dimensional arrays. You’ll learn how to declare, create, and access elements, along with examples of looping through arrays and a simple exercise to reinforce these concepts.

What Is an Array?

An array is a fixed-size collection of elements, all of the same type. Once created, the size of the array cannot change.

Think of an array as a row of numbered boxes where you can store values. Each box is called an element, and its position is called an index.

One-Dimensional Arrays

Declaring an Array

To declare a one-dimensional array, you specify the type and use square brackets:

int[] numbers;

This creates a variable numbers that can hold an array of integers but doesn’t create the array yet.

Instantiating an Array

You create the actual array with the new keyword and specify its size:

numbers = new int[5];  // An array that holds 5 integers

You can also combine declaration and instantiation:

int[] numbers = new int[5];

Initializing and Accessing Elements

You can assign values to array elements using their index, which starts at 0:

numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;

To access or print elements:

System.out.println(numbers[0]);  // Prints 10

Example: Looping Through a One-Dimensional Array

int[] numbers = {5, 10, 15, 20, 25};  // Initialize with values

for (int i = 0; i < numbers.length; i++) {
    System.out.println("Element at index " + i + " is " + numbers[i]);
}

Output:

Element at index 0 is 5
Element at index 1 is 10
Element at index 2 is 15
Element at index 3 is 20
Element at index 4 is 25

Multidimensional Arrays

A two-dimensional array can be thought of as a grid or table — rows and columns of elements.

Declaring a 2D Array

int[][] matrix;  // Declaration of a 2D integer array

Instantiating a 2D Array

matrix = new int[3][4];  // 3 rows, 4 columns

You can also combine these:

int[][] matrix = new int[3][4];

Accessing Elements in a 2D Array

You use two indices — one for the row and one for the column:

matrix[0][0] = 1;   // First row, first column
matrix[2][3] = 10;  // Third row, fourth column

Example: Nested Loop to Iterate Over a 2D Array

int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

for (int row = 0; row < matrix.length; row++) {
    for (int col = 0; col < matrix[row].length; col++) {
        System.out.print(matrix[row][col] + " ");
    }
    System.out.println();
}

Output:

1 2 3 
4 5 6 
7 8 9
Click to view full runnable Code

public class Test {
    public static void main(String[] args) {
        int[][] matrix = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };

        for (int row = 0; row < matrix.length; row++) {
            for (int col = 0; col < matrix[row].length; col++) {
                System.out.print(matrix[row][col] + " ");
            }
            System.out.println();
        }
    }
}

Exercise: Summing Elements of an Array

Try this small task:

Example code snippet:

int[] values = {3, 7, 2, 9, 4};
int sum = 0;

for (int i = 0; i < values.length; i++) {
    sum += values[i];
}

System.out.println("Sum of elements: " + sum);

Expected output:

Sum of elements: 25

Exercise: Printing a 2D Grid

Try printing a 5x5 grid of stars (*) using nested loops:

for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        System.out.print("* ");
    }
    System.out.println();
}

Output:

* * * * * 
* * * * * 
* * * * * 
* * * * * 
* * * * *

Summary

Mastering arrays is crucial since they form the foundation for more advanced data structures and algorithms in Java.

Index

5.2 Common Array Algorithms

Arrays are fundamental in programming, but just storing data isn’t enough — you need to process it efficiently. This section walks you through some essential array algorithms: finding the maximum/minimum values, reversing arrays, searching (linear and binary), and sorting (selection or bubble sort). Along the way, you’ll see how to think about algorithms and their efficiency, and then get a challenge to practice!

Finding Maximum and Minimum Values

To find the maximum or minimum in an array, you typically scan through all elements, updating your current max or min as you go.

Example: Find Maximum

public static int findMax(int[] arr) {
    int max = arr[0];  // Assume first element is max initially
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];  // Update max if current element is bigger
        }
    }
    return max;
}

Similarly, for minimum, change the comparison to arr[i] < min.

Reversing an Array

Reversing means swapping elements from the start and end moving toward the center.

public static void reverse(int[] arr) {
    int left = 0;
    int right = arr.length - 1;

    while (left < right) {
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
        left++;
        right--;
    }
}

A simple search algorithm that checks each element until it finds the target or reaches the end.

public static int linearSearch(int[] arr, int target) {
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] == target) {
            return i;  // Return index if found
        }
    }
    return -1;  // Not found
}

Efficiency: Runs in O(n) time, checking each element once.

Used on sorted arrays, binary search cuts the search space in half each time.

public static int binarySearch(int[] arr, int target) {
    int left = 0;
    int right = arr.length - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;

        if (arr[mid] == target) {
            return mid;
        } else if (arr[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;  // Not found
}

Efficiency: Runs in O(log n) time — much faster than linear search for large arrays.

Sorting Arrays

Sorting organizes elements in ascending (or descending) order. Two simple sorting algorithms are selection sort and bubble sort.

Selection Sort

Finds the smallest element and swaps it with the first unsorted element, then repeats.

public static void selectionSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int minIndex = i;

        for (int j = i + 1; j < arr.length; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }

        // Swap
        int temp = arr[minIndex];
        arr[minIndex] = arr[i];
        arr[i] = temp;
    }
}

Bubble Sort

Repeatedly swaps adjacent elements if they are in the wrong order, "bubbling" the largest element to the end.

public static void bubbleSort(int[] arr) {
    boolean swapped;

    for (int i = 0; i < arr.length - 1; i++) {
        swapped = false;

        for (int j = 0; j < arr.length - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                // Swap
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                swapped = true;
            }
        }

        // If no swaps, array is sorted
        if (!swapped) break;
    }
}
Click to view full runnable Code

public class ArrayAlgorithms {

    public static int findMax(int[] arr) {
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }

    public static int findMin(int[] arr) {
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
        }
        return min;
    }

    public static void reverse(int[] arr) {
        int left = 0, right = arr.length - 1;
        while (left < right) {
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
    }

    public static int linearSearch(int[] arr, int target) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == target) return i;
        }
        return -1;
    }

    public static int binarySearch(int[] arr, int target) {
        int left = 0, right = arr.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] == target) return mid;
            else if (arr[mid] < target) left = mid + 1;
            else right = mid - 1;
        }
        return -1;
    }

    public static void selectionSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }

    public static void bubbleSort(int[] arr) {
        boolean swapped;
        for (int i = 0; i < arr.length - 1; i++) {
            swapped = false;
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                }
            }
            if (!swapped) break;
        }
    }

    public static void printArray(int[] arr) {
        for (int val : arr) {
            System.out.print(val + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int[] array = {34, 7, 23, 32, 5, 62};

        System.out.println("Original array:");
        printArray(array);

        System.out.println("Maximum: " + findMax(array));
        System.out.println("Minimum: " + findMin(array));

        System.out.println("Reversed array:");
        reverse(array);
        printArray(array);

        int searchVal = 23;
        System.out.println("Linear search for " + searchVal + ": " + linearSearch(array, searchVal));

        selectionSort(array);
        System.out.println("Selection sorted:");
        printArray(array);

        System.out.println("Binary search for " + searchVal + ": " + binarySearch(array, searchVal));

        int[] array2 = {12, 3, 45, 2, 18};
        bubbleSort(array2);
        System.out.println("Bubble sorted another array:");
        printArray(array2);
    }
}

Reflecting on Algorithmic Thinking and Efficiency

Mini Challenge: Implement a Custom Array Filter

Try this on your own:

Summary

Mastering these fundamental algorithms will give you a strong foundation to understand more complex data structures and algorithms later.

Index

5.3 Working with Strings and StringBuilder

Strings are one of the most common data types you’ll use in Java. They allow you to store and manipulate text, from simple words to entire sentences. In this section, we’ll explore how strings work in Java, why they are immutable, and how the StringBuilder class offers an efficient way to modify text.

How Strings Work in Java

In Java, a String is an object that represents a sequence of characters, such as "Hello, world!". Java stores strings in a special memory area called the string pool. When you create a string literal, Java checks the pool first to reuse existing strings, improving performance and memory usage.

Immutability of Strings

Strings in Java are immutable, meaning once created, they cannot be changed. Any operation that seems to modify a string actually creates a new string object.

Example:

String s = "Hello";
s = s + " World";  // Creates a new string "Hello World"

The original "Hello" string remains unchanged, and s now points to the new string.

Common String Methods

Here are some useful methods to work with strings:

.length()

Returns the number of characters in the string.

String text = "Java";
System.out.println(text.length());  // Output: 4

.charAt(int index)

Returns the character at the specified position (index starts at 0).

char c = text.charAt(1);
System.out.println(c);  // Output: 'a'

.substring(int beginIndex, int endIndex)

Returns a substring from beginIndex up to (but not including) endIndex.

String sub = text.substring(1, 3);
System.out.println(sub);  // Output: "av"

.indexOf(String str)

Returns the index of the first occurrence of the specified substring, or -1 if not found.

int pos = text.indexOf("va");
System.out.println(pos);  // Output: 1

String Concatenation and Performance

Using the + operator to join strings is easy but can be inefficient if done repeatedly inside loops because it creates many temporary String objects.

Introducing StringBuilder for Mutable Strings

StringBuilder is a class designed to create and modify strings efficiently. Unlike String, a StringBuilder object is mutable, so you can append, insert, or delete characters without creating new objects each time.

Creating and Using a StringBuilder

StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb.toString());  // Output: Hello World

You can chain calls:

sb.append("!").append(" How are you?");

Modifying Text with StringBuilder

Example: Building a Sentence with StringBuilder

public class StringBuilderDemo {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Java");

        sb.append(" is");
        sb.append(" fun");
        sb.insert(9, " really");
        sb.replace(0, 4, "Programming");

        System.out.println(sb.toString());
    }
}

Output:

Programming is really fun

Comparison Table: String vs. StringBuilder

Feature String StringBuilder
Mutability Immutable Mutable
Modification Creates new object on change Modifies same object
Performance (repeated concatenation) Slow (due to object creation) Fast (efficient in loops)
Thread safety Thread-safe (immutable) Not thread-safe
Common use cases Fixed or rarely changed text Building/modifying text dynamically

Summary

Try experimenting with String and StringBuilder in your own programs to see how they behave differently and to improve the performance of your text-processing code.

Index

5.4 String Comparison and Manipulation

Working with strings often requires comparing their content and manipulating their text. Java provides several ways to compare strings and methods to perform common string transformations. This section explains the differences between these approaches and shows practical examples.

Comparing Strings: .equals(), .equalsIgnoreCase(), and ==

.equals() Comparing Content

The .equals() method compares the actual content of two strings:

String a = "Java";
String b = new String("Java");

System.out.println(a.equals(b));  // true, because content is the same

.equalsIgnoreCase() Case-Insensitive Comparison

If you need to compare strings ignoring uppercase or lowercase differences, use .equalsIgnoreCase():

String a = "Java";
String b = "java";

System.out.println(a.equalsIgnoreCase(b));  // true

== Comparing References (Memory Locations)

Using == checks if two variables point to the exact same object in memory, not if their contents match:

String a = "Java";
String b = new String("Java");

System.out.println(a == b);  // false, different objects

Pitfall: Since many strings can have the same content but be different objects, == can give unexpected results when comparing strings.

Practical String Manipulation Methods

Removing Whitespace: .trim()

Removes leading and trailing spaces from a string.

String input = "  Hello World  ";
System.out.println("[" + input.trim() + "]");  // Output: [Hello World]

Splitting Strings: .split()

Splits a string into parts based on a delimiter, returning an array.

String csv = "apple,banana,orange";
String[] fruits = csv.split(",");

for (String fruit : fruits) {
    System.out.println(fruit);
}

Output:

apple  
banana  
orange

Replacing Substrings: .replace()

Replaces occurrences of a target substring with another string.

String text = "I like cats";
String newText = text.replace("cats", "dogs");
System.out.println(newText);  // Output: I like dogs

Exercise: Check if a String is a Palindrome

A palindrome reads the same forwards and backwards, like "madam".

public static boolean isPalindrome(String str) {
    str = str.toLowerCase().replaceAll("\\s+", ""); // Normalize: lowercase, remove spaces

    int left = 0;
    int right = str.length() - 1;

    while (left < right) {
        if (str.charAt(left) != str.charAt(right)) {
            return false;
        }
        left++;
        right--;
    }
    return true;
}

Example usage:

System.out.println(isPalindrome("Race car"));  // true
System.out.println(isPalindrome("Hello"));     // false
Click to view full runnable Code

public class PalindromeChecker {

    public static boolean isPalindrome(String str) {
        str = str.toLowerCase().replaceAll("\\s+", ""); // Normalize: lowercase, remove spaces

        int left = 0;
        int right = str.length() - 1;

        while (left < right) {
            if (str.charAt(left) != str.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println(isPalindrome("Race car"));  // true
        System.out.println(isPalindrome("Hello"));     // false
        System.out.println(isPalindrome("A Santa at NASA")); // true
    }
}

Summary

By understanding how to correctly compare and manipulate strings, you’ll avoid bugs and write cleaner, more effective Java programs.

Index