Skip to Content
Course content

240: Implementing Sorting Algorithms in Java

Click on the "Edit" button in the top corner of the screen to edit your slide content.

When you first start thinking about sorting, the most intuitive approach is usually the worst one. We've all been there. You have a list of items—say, a collection of Product objects with prices—and you just want them in order. The most natural impulse is to just keep swapping neighbors until the biggest one "bubbles" to the top. It feels logical because it's how a human might sort a small handful of physical cards on a table.

The temptation of the nested loop

Let's look at the "naive" way. I'm talking about the classic Bubble Sort. If you're sorting a small array of products by price, it looks something like this:

public void bubbleSort(Product[] products) {
    int n = products.length;
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (products[j].getPrice() > products[j + 1].getPrice()) {
                // Swap them
                Product temp = products[j];
                products[j] = products[j + 1];
                products[j + 1] = temp;
            }
        }
    }
}

On the surface, it works. If you have ten products, it's fine. But here is where you'll run into trouble: the time complexity is O(n²). In plain English, if you double the number of products, the time it takes to sort them doesn't double—it quadruples. I've seen developers commit this kind of logic into a codebase that worked perfectly in staging with 50 records, only to have the entire application freeze in production when the dataset grew to 50,000. The CPU just starts spinning its wheels because it's performing an astronomical number of redundant comparisons.

The elegance of splitting the problem

To do this properly, we need to stop thinking about the list as one giant block and start thinking about it as a series of tiny problems. This is where Merge Sort comes in. Instead of scanning the whole list over and over, we split the array in half, sort those halves, and then merge them back together. It’s a "divide and conquer" strategy.

Here is how I'd implement a more professional, scalable version:

public void mergeSort(Product[] products, int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2;

        mergeSort(products, left, mid);
        mergeSort(products, mid + 1, right);

        merge(products, left, mid, right);
    }
}

private void merge(Product[] products, int left, int mid, int right) {
    int n1 = mid - left + 1;
    int n2 = right - mid;

    Product[] L = new Product[n1];
    Product[] R = new Product[n2];

    System.arraycopy(products, left, L, 0, n1);
    System.arraycopy(products, mid + 1, R, 0, n2);

    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (L[i].getPrice() <= R[j].getPrice()) {
            products[k++] = L[i++];
        } else {
            products[k++] = R[j++];
        }
    }

    while (i < n1) products[k++] = L[i++];
    while (j < n2) products[k++] = R[j++];
}

Trading memory for speed

Now, you might notice that Merge Sort is more complex to write and, crucially, it uses more memory. While Bubble Sort sorts "in-place," Merge Sort creates temporary arrays during the merge process. In the industry, we call this a space-time tradeoff. You're spending a bit more RAM to gain a massive increase in speed.

The time complexity drops from O(n²) to O(n log n). To put that in perspective: for a list of 10,000 items, Bubble Sort might take 100,000,000 operations. Merge Sort would take roughly 130,000. The difference isn't just "a bit faster"—it's the difference between a responsive app and a crashed server. If you're building something that needs to scale, always lean toward the logarithmic approach, even if the implementation feels a bit more verbose.




📋 Practical Task

Implementing a High-Score Leaderboard Sorter

You are building a gaming leaderboard. You have a Player class with two fields: String username and int score. Your task is to implement a sorting mechanism that ranks players from highest score to lowest score (descending order).

Requirements:

  • Create a Player class with the necessary fields and getters.
  • Implement a sorting algorithm (Merge Sort is recommended) in a LeaderboardManager class.
  • Ensure the sort is descending (the player with the highest score must be at index 0).
  • Test your implementation with an array of at least 10 players with varying scores to verify that the ranking is correct.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.