Build a Java Generics Playlist

Build a console playlist manager with type-safe Java ArrayLists.

Introduction

30 Second Summary

Music playlists feel predictable because every entry looks like a song title. One stray number can stay hidden until the program treats it like text and crashes.

In this project, you will build a console playlist manager in Java with IntelliJ IDEA. You will watch a raw type fail at runtime before rebuilding the playlist with generics that protect every song title.

What You'll Build

You will run your playlist manager and watch every song operation report its result in IntelliJ IDEA's Run tool window.

By the end of this project, you'll have:

  • A before-and-after failure demo where a mixed playlist prints successfully before a ClassCastException exposes the hidden unsafe value.
  • A playlist with compile-time type safety through ArrayList<String> plus the diamond operator. All three song titles print without a cast.
  • A reusable playlist manager whose helper methods add, display, search, update, and safely remove songs with Iterator<String>.
  • Secret Mission: Upgrade the manager to store titles with ratings in Song objects. The upgraded playlist filters songs rated 4 or 5.

Are there any prerequisites?

You'll need a Windows computer with IntelliJ IDEA and a Java Development Kit already installed. Basic familiarity with Java variables, methods, and loops helps you focus on collections.

Before We Start

This is your moment to commit to the console playlist manager before you write any code. Understanding why a typed ArrayList restricts its element type gives every later change a clear purpose.

Set Up the Java Project

Your playlist needs a dependable place to compile each change. It also needs a quick way to run the result.

A plain Java project lets IntelliJ IDEA compile the code with your installed JDK. Maven or Gradle would add setup without teaching generics.

In this step, get ready to:
  • Create a plain Java project with the installed JDK.
  • Add the playlist manager entry point.
  • Verify the class through its console output.
Create the plain Java project

The project wizard connects your source files to the installed Java compiler. The IntelliJ build system gives this small program the simplest project structure.

  • Press the Windows key to open Windows Search.
  • Type IntelliJ IDEA into Windows Search.
  • Press Enter to open IntelliJ IDEA.

The IntelliJ IDEA welcome screen gives you the option to start a project.

  • Click New Project.
  • Select Java from the project list.

Why Use the IntelliJ Build System?

This console program only uses the Java standard library. The IntelliJ build system can compile it without extra build files or external dependencies.

  • Enter GenericPlaylistManager as the project name.
  • Select your installed JDK from the JDK list.

The wizard now points this project at the Java compiler already installed on your computer.

  • Select IntelliJ as the build system.
  • Leave Add sample code disabled.

The project is now configured as an empty Java workspace.

  • Click Create.

The Project tool window should show GenericPlaylistManager with a src folder.

That workspace is ready for your first runnable class.

Installed JDK Missing?

  • Select Add JDK from Disk… from the JDK list.
  • Choose the folder containing the installed JDK.

Help me find the installed JDK for my IntelliJ IDEA project.

Add the runnable class

Java starts this console application from the public static void main(String[] args) entry point. The class prints a short setup signal so you can prove the project runs.

  • Select the src folder in the Project tool window.
  • Press Alt+Insert to open the new-item menu.

The menu now shows the file types available inside the Java source folder.

  • Select Java Class.

The class-name field opens for the new file.

  • Type PlaylistManager as the class name.
  • Press Enter to create the class.

IntelliJ IDEA opens src/PlaylistManager.java with a generated class declaration.

  • Replace the generated contents of src/PlaylistManager.java by pasting the code below:
public class PlaylistManager {
    public static void main(String[] args) {
        System.out.println("Playlist Manager ready.");
    }
}

What Does This Code Do?

  • The PlaylistManager class provides a home for the console program.
  • The main(String[] args) method gives Java the application entry point.
  • The System.out.println call prints Playlist Manager ready. as a visible setup check.
  • Press Ctrl+S to save src/PlaylistManager.java.
  • Confirm that the green Run icon appears in the gutter beside main.

Run Icon Missing?

  • Confirm that src/PlaylistManager.java contains the complete PlaylistManager class.
  • Check that the project still uses your installed JDK.

Help me restore the gutter Run icon for my Java main method.

✔️ Awesome, I've got everything!

Your saved class has the expected entry point. You are ready to run it.

ⓧ I'd like to double check the full code

public class PlaylistManager {
    public static void main(String[] args) {
        System.out.println("Playlist Manager ready.");
    }
}

What Should Match?

This complete file defines the entry point and prints a clear setup signal. Matching it removes generated code that could change the first run.

Run the setup check

The first run checks the entire setup in one pass. IntelliJ IDEA compiles the class before showing the program output in the Run tool window.

Before you click Run, what confirmation do you expect the program to print?

  • Click the green gutter icon beside main.
  • Select Run.

The Run tool window prints Playlist Manager ready..

You should also see exit code 0. That first run proves your Java project compiles successfully.

Setup Message Missing?

  • Confirm that src/PlaylistManager.java matches the full-code tab.
  • Confirm that the project still uses the installed JDK.

Help me diagnose why my PlaylistManager class does not print the setup message.

Your plain Java project now has a working entry point. Next, you'll turn this setup signal into the first visible playlist.

Build a Mixed-Type Playlist

Your Java program already runs. It does not hold any playlist data yet.

A raw ArrayList accepts values without enforcing one element type. You’ll use that flexibility to store two song titles plus a number in the same playlist.

An enhanced for loop reads each stored item in turn. Printing the loop variable makes the mixed values visible.

In this step, get ready to:
  • Create a raw ArrayList for the playlist.
  • Add two song-title strings plus the integer 5.
  • Print each item with an enhanced for loop.
Create the raw playlist

A raw list can hold values with different types. This first version stores two String values plus one Integer value.

  • In IntelliJ IDEA, return to src/PlaylistManager.java.
  • Select the existing contents of src/PlaylistManager.java.
  • Create the raw playlist by replacing the selected code with the code below:
import java.util.ArrayList;

public class PlaylistManager {
    public static void main(String[] args) {
        ArrayList playlist = new ArrayList();

        playlist.add("Midnight Drive");
        playlist.add(5);
        playlist.add("Ocean Lights");
    }
}

What does this code do?

  • The import java.util.ArrayList line makes the collection class available to PlaylistManager.
  • The raw declaration creates a resizable list without a required element type.
  • The three add calls append Midnight Drive, 5, plus Ocean Lights in that order.
  • Save src/PlaylistManager.java.
  • Click the green gutter Run icon beside main.

The Run tool window reports exit code 0. This confirms the mixed values can live in the same raw list.

That is a strong start because your playlist now stores text values plus the integer 5.

Does the Class Fail to Run?

  • Confirm import java.util.ArrayList appears above the PlaylistManager class.
  • Check that every opening brace has a matching closing brace.

Help me fix my mixed-type Java playlist without changing its raw ArrayList design.

Print every playlist item

The playlist data becomes useful once you can see it. An Object loop variable can receive every value stored in this raw list.

  • Complete src/PlaylistManager.java by replacing its contents with the code below:
import java.util.ArrayList;

public class PlaylistManager {
    public static void main(String[] args) {
        ArrayList playlist = new ArrayList();

        playlist.add("Midnight Drive");
        playlist.add(5);
        playlist.add("Ocean Lights");

        for (Object item : playlist) {
            System.out.println(item);
        }
    }
}

How Does the Loop Work?

  • The for (Object item : playlist) loop visits each playlist entry in insertion order.
  • The Object type lets item receive both the song-title strings plus the integer.
  • The System.out.println(item) call prints the current value on its own line.
  • Save src/PlaylistManager.java.

Before you run the finished class, what three values do you expect to see in the Run tool window?

  • Click the green gutter Run icon beside main.

You’ll see Midnight Drive, 5, plus Ocean Lights on separate lines in that order.

You now have your first visible playlist. Its mixed output proves that the raw list accepted both text and a number.

Missing a Playlist Item?

  • Confirm the enhanced for loop sits below the third add call inside main.
  • Check that the loop variable uses Object as its type.
  • Confirm each add call appears before the loop.

Help me find why my raw Java playlist does not print all three values in order.

✔️ Awesome, I've got everything!

Your raw playlist stores three mixed values. The Run tool window prints each value in insertion order.

ⓧ I'd like to double check the full code

import java.util.ArrayList;

public class PlaylistManager {
    public static void main(String[] args) {
        ArrayList playlist = new ArrayList();

        playlist.add("Midnight Drive");
        playlist.add(5);
        playlist.add("Ocean Lights");

        for (Object item : playlist) {
            System.out.println(item);
        }
    }
}

Your mixed-type playlist is visible. Next, you’ll test what happens when the program assumes every stored value is a song title.

Trigger the Type Problem

Your raw playlist now prints song titles beside the number 5 in IntelliJ IDEA. That visible mix proves a raw type accepts values without enforcing one element type.

The program has no guarantee that every item is a song title. This step makes that assumption explicit so Java can test it at runtime.

In this step, get ready to:
  • Add an explicit cast to the enhanced for loop.
  • Run the mixed playlist under the new assumption.
  • Trace the runtime result back to the cast line.
Cast every playlist item to String

An explicit cast tells Java to treat the current Object as a String. Assigning the result to song makes the assumption visible inside the loop.

  • In src/PlaylistManager.java, find the loop that starts with for (Object item : playlist).
  • Replace the entire loop with this type-assumption test:
for (Object item : playlist) {
    String song = (String) item;
    System.out.println(song);
}

What does this code do?

  • The cast asks Java to treat each item as a String.
  • The song variable holds the result when the runtime accepts that conversion.
  • The print statement now relies on the list item being a song title.
  • Save src/PlaylistManager.java.
Run the unsafe assumption

The playlist still contains the same three values. Running the class now tests whether each value can pass the cast.

Before you run it, predict whether all three values can become String values.

  • Click the green Run gutter icon beside main.

You'll see Midnight Drive print first. The Run tool window then reports ClassCastException at the cast line when the program reaches the Integer value 5.

Why does the cast fail?

  • The first item is a String. Its cast succeeds, so Midnight Drive prints.
  • The next item is an Integer. Its cast to String triggers ClassCastException at runtime.
  • The raw list accepted both values because it did not enforce one element type.

You have exposed the exact weakness hidden by the earlier successful output.

No ClassCastException?

  • Confirm the number 5 still sits between the two song titles.
  • Confirm the loop stores the cast of item in song.
  • Save src/PlaylistManager.java before clicking the gutter icon again.

Help me diagnose why my raw Java playlist does not produce the expected runtime cast failure.

✔️ Awesome, I've got everything!

Your file keeps the mixed raw list intact. The loop now makes the String assumption explicit.

ⓧ I'd like to double check the full code

Compare your file with this complete version.

import java.util.ArrayList;

public class PlaylistManager {
    public static void main(String[] args) {
        ArrayList playlist = new ArrayList();

        playlist.add("Midnight Drive");
        playlist.add(5);
        playlist.add("Ocean Lights");

        for (Object item : playlist) {
            String song = (String) item;
            System.out.println(song);
        }
    }
}

What should match?

  • The raw ArrayList declaration remains unchanged.
  • The playlist still contains the number 5.
  • The loop casts each item into the song variable before printing.

The runtime failure now has a precise cause. Next, you'll use ArrayList<String> so the compiler can stop this mistake before the program runs.

Fix the Playlist with Generics

Your raw playlist accepted the number 5. The cast turned that flexibility into a ClassCastException at runtime.

Java generics move the type check into the editor. ArrayList<String> makes every list operation promise to use song-title strings.

In this step, get ready to:
  • Parameterize the raw playlist with a string element type.
  • Observe the compiler reject the integer value.
  • Run a string-only playlist without an explicit cast.
Parameterize the playlist

A parameterized type declares the kind of element a collection can hold. ArrayList<String> limits this playlist to String values.

  • In src/PlaylistManager.java, locate the raw declaration inside main(String[] args).
ArrayList playlist = new ArrayList();

What does the raw declaration allow?

The declaration has no element type. The playlist can therefore accept strings or integers without a compile-time type check.

  • Replace the raw declaration with this parameterized declaration:
ArrayList<String> playlist = new ArrayList<>();

How does the generic declaration work?

  • The String type argument defines the only element type this playlist accepts.
  • The diamond operator lets Java infer the constructor type from the declaration.
  • This creates compile-time type safety for additions and retrievals.

Before you test this change, predict whether playlist.add(5) can still compile now that the playlist promises to store strings.

  • Test the changed declaration by clicking the green gutter Run icon beside main.

IntelliJ IDEA marks playlist.add(5) as a type error. Compilation stops before the old cast can cause another runtime crash.

That failed compilation is intentional. You have moved the type mistake from runtime to the compiler.

Is the integer still accepted?

Confirm that the declaration contains ArrayList<String> on the left side. Check that the constructor uses new ArrayList<>().

If the editor still treats the list as raw, help me check why my parameterized ArrayList is not rejecting an Integer.

Make every playlist element a string

The editor has identified the mixed-type operation. Replacing that value makes every playlist item match the declared element type.

  • In src/PlaylistManager.java, locate the integer addition:
playlist.add(5);

Why is this line rejected?

The value 5 is an integer. It does not satisfy the playlist's String element type.

  • Replace the integer addition with this song title:
playlist.add("City Rain");

Why does this value fit?

The quoted title is a String. It satisfies the generic type declared by the playlist.

  • Locate the loop that receives each item as an Object.
for (Object item : playlist) {
    String song = (String) item;
    System.out.println(song);
}

Where did the cast come from?

The raw list returned each value as an Object. The explicit cast forced Java to treat each value as a String at runtime.

  • Replace the loop with this typed version:
for (String song : playlist) {
    System.out.println(song);
}

Why does the typed loop work?

The enhanced for loop receives each element as a String. The generic playlist removes the need for an explicit cast.

Run the type-safe playlist

The declaration now agrees with every stored value. The loop also uses the same element type.

Before the final run, predict whether the old cast failure can still occur with these three string values.

  • Run the corrected class by clicking the green gutter Run icon beside main.

The Run tool window prints Midnight Drive, City Rain, and Ocean Lights on separate lines. It reports exit code 0.

You've closed the gap. The playlist now prevents mixed-type additions before the program runs.

Still seeing a cast failure?

Check that every playlist.add value is inside double quotes. Confirm that the loop begins with for (String song : playlist).

If the class still fails, help me compare my typed playlist with the expected String-only version.

✔️ Awesome, I've got everything!

Your playlist now stores only song-title strings. The program runs without an explicit cast or unchecked raw-type warning.

ⓧ I'd like to double check the full code

import java.util.ArrayList;

public class PlaylistManager {
    public static void main(String[] args) {
        ArrayList<String> playlist = new ArrayList<>();

        playlist.add("Midnight Drive");
        playlist.add("City Rain");
        playlist.add("Ocean Lights");

        for (String song : playlist) {
            System.out.println(song);
        }
    }
}

What should you compare?

Each list entry is a String. The loop receives each entry through the typed song variable.

Your playlist is type-safe and running again. Next, you'll turn its common operations into focused manager methods.

Build Playlist Manager Operations

Your typed playlist now uses Java's Collections Framework to keep every item as a song title. However, all of its work still sits inside main().

Focused methods give each playlist operation a clear purpose. You will turn the typed list into a manager that can add, display, search, rename, plus remove songs.

In this step, get ready to:
  • Organize playlist operations into focused methods.
  • Use typed list methods to search for titles plus rename songs.
  • Remove a matching song safely with a typed iterator.
Add songs and display numbered positions

The first two helpers separate playlist creation from playlist presentation. This keeps main() focused on the demonstration sequence.

  • In IntelliJ IDEA, place your cursor after the closing brace of main().
  • Add the song helper by pasting this method:
    public static void addSong(ArrayList<String> playlist, String title) {
        playlist.add(title);
        System.out.println("Song added: " + title);
    }

What does this method do?

  • The playlist parameter receives the typed list that the method changes.
  • The title parameter holds the song title being added.
  • The confirmation message makes each addition visible in the Run tool window.
  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

The Run tool window still prints the three existing titles. Reaching the output without a compilation error confirms that addSong() is ready to use.

Does the new method fail to compile?

Check that addSong() sits inside the PlaylistManager class. Its closing brace must appear before the class's final brace.

Help me fix the placement or syntax of my addSong method.

  • Select the three playlist.add lines inside main().
  • Replace the selected lines with these helper calls:
        addSong(playlist, "Midnight Drive");
        addSong(playlist, "Ocean Lights");
        addSong(playlist, "City Rain");

Why pass the playlist into each call?

Each call gives addSong() the same typed list. The second argument supplies the title for that specific addition.

  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

You will see three Song added: messages before the existing title output. The messages prove that main() now builds the playlist through addSong().

Missing a song-added message?

Confirm that all three direct additions were replaced with addSong() calls. Check that each call passes playlist as its first argument.

Help me find why my addSong calls do not print all three confirmations.

  • Place your cursor after the closing brace of addSong().
  • Add the numbered display helper by pasting this method:
    public static void displayPlaylist(ArrayList<String> playlist) {
        System.out.println();
        System.out.println("Playlist:");

        int position = 1;
        for (String song : playlist) {
            System.out.println(position + ". " + song);
            position++;
        }
    }

How does the numbering work?

  • The position variable starts the visible numbering at 1.
  • The enhanced for loop retrieves each title as a String.
  • The increment prepares the next position after each title is printed.
  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

The existing output still reaches all three titles. This successful run confirms that displayPlaylist() compiles before it replaces the loop.

Does the display helper show a syntax error?

Check that position is declared before the loop. Confirm that the loop variable is spelled song everywhere inside the loop.

Help me fix my displayPlaylist method while preserving numbered output.

  • Select the existing enhanced for loop inside main().
  • Replace the selected loop with this method call:
        displayPlaylist(playlist);

What changes in main?

The display details now live inside displayPlaylist(). The call keeps the demonstration sequence short.

  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

That first manager view is working. You will see a Playlist: heading followed by three numbered song titles.

Still seeing unnumbered titles?

Confirm that the enhanced for loop was removed from main(). Check that displayPlaylist(playlist) appears after the three additions.

Help me find why displayPlaylist is not showing numbered titles.

Search and update titles

A manager needs to answer whether a title exists before changing it. The typed list provides focused operations for both jobs.

  • Place your cursor after the closing brace of displayPlaylist().
  • Add the search helper by pasting this method:
    public static void searchSong(ArrayList<String> playlist, String title) {
        if (playlist.contains(title)) {
            System.out.println("Found: " + title);
        } else {
            System.out.println("Not found: " + title);
        }
    }

How does the search work?

The contains() check reports whether the requested title is in the list. The two messages make either result visible.

  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

The program still reaches the numbered playlist without a compilation error. This confirms that searchSong() is ready to call.

  • Find the first displayPlaylist(playlist) call inside main().
  • Add this search call directly below it:
        searchSong(playlist, "Ocean Lights");

What does this call test?

The call searches the existing typed list for Ocean Lights. Its position after the first display keeps the demonstration easy to follow.

  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

The Run tool window prints Found: Ocean Lights after the first playlist. Your manager can now confirm that a requested title exists.

Does the search report not found?

Check that the call uses the exact title Ocean Lights. Confirm that the same title is passed to addSong() earlier in main().

Help me diagnose why searchSong cannot find Ocean Lights.

  • Place your cursor after the closing brace of searchSong().
  • Add the update helper by pasting this method:
    public static void updateSong(
            ArrayList<String> playlist,
            String oldTitle,
            String newTitle
    ) {
        int index = playlist.indexOf(oldTitle);

        if (index >= 0) {
            playlist.set(index, newTitle);
            System.out.println("Updated: " + oldTitle + " -> " + newTitle);
        } else {
            System.out.println("Cannot update. Not found: " + oldTitle);
        }
    }

How does the update work?

  • The indexOf() call finds the position of oldTitle.
  • An index of 0 or higher means the title exists.
  • The set() call replaces the title at that position.
  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

The program still prints the playlist plus the successful search result. Reaching both outputs confirms that updateSong() compiles.

  • Find the searchSong(playlist, "Ocean Lights") call inside main().
  • Add this update call directly below it:
        updateSong(playlist, "City Rain", "City Rain (Acoustic)");

What does this call change?

The call locates City Rain by its current title. It replaces that element with City Rain (Acoustic).

  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

You will see Updated: City Rain -> City Rain (Acoustic) after the search result. The list now holds the renamed title.

Does the update say the title is missing?

Check that City Rain is added before updateSong() runs. Confirm that indexOf() receives oldTitle.

Help me diagnose why updateSong cannot rename City Rain.

Remove a song with a typed iterator

An iterator tracks traversal through the playlist. Its removal operation safely deletes the element most recently returned during that traversal.

  • Select the import section at the top of src/PlaylistManager.java.
  • Replace that section with these imports:
import java.util.ArrayList;
import java.util.Iterator;

Why import Iterator?

The Iterator type belongs to java.util. Importing it lets the removal method declare a typed Iterator<String>.

  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

The program reaches the update confirmation without an import error. The iterator type is now available to the class.

Is Iterator still unresolved?

Confirm that the import appears above the PlaylistManager class declaration. Check the capitalization in java.util.Iterator.

Help me fix an unresolved Iterator import in my Java class.

  • Place your cursor after the closing brace of updateSong().
  • Add the removal helper by pasting this method:
    public static void removeSong(ArrayList<String> playlist, String title) {
        Iterator<String> iterator = playlist.iterator();

        while (iterator.hasNext()) {
            String song = iterator.next();

            if (song.equals(title)) {
                iterator.remove();
                System.out.println("Removed: " + title);
                return;
            }
        }

        System.out.println("Cannot remove. Not found: " + title);
    }

How does safe removal work?

  • The hasNext() check keeps the loop running while another song remains.
  • The next() call retrieves that song as a String.
  • The remove() call deletes the matching song returned by next().
  • The return statement stops the method after the first match is removed.
  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

The program still reaches the update confirmation without a compilation error. This proves that the typed iterator method is valid.

Does the iterator method fail to compile?

Check that the iterator type is Iterator<String>. Confirm that next() runs before remove() inside the loop.

Help me fix my typed iterator removal method.

  • Find the updateSong() call inside main().
  • Add these final demonstration calls directly below it:
        removeSong(playlist, "Midnight Drive");
        displayPlaylist(playlist);

Why display the playlist again?

The removal call deletes Midnight Drive. The final display exposes the changed list immediately.

Before the final run, consider whether Midnight Drive will still appear in the last playlist.

  • Save src/PlaylistManager.java.
  • Click the green gutter icon beside main().
  • Select Run from the menu.

What should you see?

  • The first playlist shows Midnight Drive, Ocean Lights, plus City Rain.
  • The search result prints Found: Ocean Lights.
  • The update result confirms that City Rain became City Rain (Acoustic).
  • The removal result prints Removed: Midnight Drive.
  • The final playlist contains Ocean Lights plus City Rain (Acoustic).

Does the final playlist look wrong?

Check the order of the method calls inside main(). The update must run before removal.

Help me compare my playlist manager output with the intended demonstration sequence.

You have turned a typed list into a working playlist manager. Every operation now has a focused method plus a visible result.

✔️ Awesome, I've got everything!

Your methods plus demonstration sequence match the finished playlist manager.

ⓧ I'd like to double check the full code

import java.util.ArrayList;
import java.util.Iterator;

public class PlaylistManager {
    public static void main(String[] args) {
        ArrayList<String> playlist = new ArrayList<>();

        addSong(playlist, "Midnight Drive");
        addSong(playlist, "Ocean Lights");
        addSong(playlist, "City Rain");

        displayPlaylist(playlist);
        searchSong(playlist, "Ocean Lights");
        updateSong(playlist, "City Rain", "City Rain (Acoustic)");
        removeSong(playlist, "Midnight Drive");
        displayPlaylist(playlist);
    }

    public static void addSong(ArrayList<String> playlist, String title) {
        playlist.add(title);
        System.out.println("Song added: " + title);
    }

    public static void displayPlaylist(ArrayList<String> playlist) {
        System.out.println();
        System.out.println("Playlist:");

        int position = 1;
        for (String song : playlist) {
            System.out.println(position + ". " + song);
            position++;
        }
    }

    public static void searchSong(ArrayList<String> playlist, String title) {
        if (playlist.contains(title)) {
            System.out.println("Found: " + title);
        } else {
            System.out.println("Not found: " + title);
        }
    }

    public static void updateSong(
            ArrayList<String> playlist,
            String oldTitle,
            String newTitle
    ) {
        int index = playlist.indexOf(oldTitle);

        if (index >= 0) {
            playlist.set(index, newTitle);
            System.out.println("Updated: " + oldTitle + " -> " + newTitle);
        } else {
            System.out.println("Cannot update. Not found: " + oldTitle);
        }
    }

    public static void removeSong(ArrayList<String> playlist, String title) {
        Iterator<String> iterator = playlist.iterator();

        while (iterator.hasNext()) {
            String song = iterator.next();

            if (song.equals(title)) {
                iterator.remove();
                System.out.println("Removed: " + title);
                return;
            }
        }

        System.out.println("Cannot remove. Not found: " + title);
    }
}

Secret mission

Store Complete Song Objects

Upgrade the playlist to store each title with a rating inside a Song object. Filter the finished playlist so only songs rated 4 or 5 appear in the highly rated section.

Clean Up Your Resources

Clean Up Your Resources

Choose whether to keep the project available, close it for later, or delete it entirely. Everything stays on your Windows computer, so there are no cloud resources or ongoing costs.

Resources you used:

  • The local GenericPlaylistManager folder containing src/PlaylistManager.java and src/Song.java.

Keep everything running

No cleanup is required because the console program exits after each run. Choose this option if you want the source ready for more practice.

  • Save src/PlaylistManager.java in IntelliJ IDEA.
  • Save src/Song.java in IntelliJ IDEA.
  • Keep the GenericPlaylistManager folder on your computer.

Pause - I'll come back to this later

The console program has already stopped. Pausing means closing the editor while preserving your project files.

  • Save src/PlaylistManager.java in IntelliJ IDEA.
  • Save src/Song.java in IntelliJ IDEA.
  • Close IntelliJ IDEA.
  • Keep the GenericPlaylistManager folder on your computer.
  • Open GenericPlaylistManager in IntelliJ IDEA when you return.

Delete - I don't want to use this again

Deleting the folder removes only the playlist source. Your development tools stay installed.

  • Close IntelliJ IDEA.
  • Locate the GenericPlaylistManager folder in your Windows file browser.
  • Permanently delete the GenericPlaylistManager folder through the file browser.
  • Search your computer for GenericPlaylistManager.

You should find no remaining project folder. This confirms that src/PlaylistManager.java and src/Song.java were removed with it.

Nice Work!

Nice Work!

You did it! You've built a Java console playlist manager that demonstrates why typed collections matter. Your program now manages complete song data through clear collection operations.

What you learned:

  • Built a runnable playlist manager in IntelliJ IDEA. Proved each playlist operation through visible console output.
  • Exposed the risk of raw types by triggering a ClassCastException. Rebuilt the playlist with ArrayList<String>. Used the diamond operator to keep the constructor concise.
  • Organized typed collection operations into focused helper methods. Traversed songs with an enhanced for loop. Used Iterator<String> to remove a matching song safely during traversal.
  • Secret Mission: Modeled complete song objects with the Song class. Upgraded the manager to ArrayList<Song>. Filtered the playlist with displayHighlyRatedSongs() so only ratings of 4 or 5 appear in the highly rated section.

Ready to quiz yourself?