Proyek Akhir: Aplikasi Daftar Tugas

Menggabungkan record, ArrayList, enum, Stream, exception, dan penyimpanan berkas (java.nio.file) menjadi aplikasi konsol Daftar Tugas.

Part 17 dari 17 ± 70 menit Gratis

Tujuan proyek

Kita membuat aplikasi konsol Daftar Tugas yang bisa menambah tugas, menandai selesai, menampilkan daftar, menghitung statistik, dan menyimpan ke berkas. Proyek ini memakai hampir semua yang sudah kamu pelajari: class/record, enum, koleksi, exception, lambda, dan Stream.

Rancangan

BagianDipakai untuk
record Tugas(String judul, boolean selesai)data tugas yang immutable
List<Tugas>menyimpan semua tugas
Streammenyaring & menghitung tugas selesai
Scannermenu interaktif
Filessimpan & muat dari berkas teks

Langkah 1 — model data

record Tugas(String judul, boolean selesai) {
    Tugas selesaikan() {
        return new Tugas(judul, true);      // record immutable: buat objek baru
    }
}

Langkah 2 — class pengelola

import java.util.ArrayList;
import java.util.List;

class DaftarTugas {
    private final List<Tugas> daftar = new ArrayList<>();

    void tambah(String judul) {
        if (judul == null || judul.isBlank()) {
            throw new IllegalArgumentException("Judul tidak boleh kosong");
        }
        daftar.add(new Tugas(judul.trim(), false));
    }

    void selesaikan(int nomor) {                      // nomor mulai dari 1
        if (nomor < 1 || nomor > daftar.size()) {
            throw new IllegalArgumentException("Nomor tidak valid: " + nomor);
        }
        daftar.set(nomor - 1, daftar.get(nomor - 1).selesaikan());
    }

    long jumlahSelesai() {
        return daftar.stream().filter(Tugas::selesai).count();
    }

    void cetak() {
        if (daftar.isEmpty()) {
            System.out.println("(belum ada tugas)");
            return;
        }
        for (int i = 0; i < daftar.size(); i++) {
            Tugas t = daftar.get(i);
            System.out.println((i + 1) + ". [" + (t.selesai() ? "x" : " ") + "] " + t.judul());
        }
    }

    List<Tugas> semua() {
        return List.copyOf(daftar);     // salinan read-only: jaga enkapsulasi
    }
}

Perhatikan semua() mengembalikan salinan, bukan list aslinya, agar kode luar tidak bisa merusak data di dalam — itu enkapsulasi yang sungguhan.

Langkah 3 — menu interaktif

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        DaftarTugas tugas = new DaftarTugas();
        try (Scanner in = new Scanner(System.in)) {
            boolean jalan = true;
            while (jalan) {
                System.out.println("\n1) Tambah  2) Selesai  3) Lihat  4) Statistik  0) Keluar");
                System.out.print("Pilih: ");
                String pilih = in.nextLine().trim();

                try {
                    switch (pilih) {
                        case "1" -> {
                            System.out.print("Judul: ");
                            tugas.tambah(in.nextLine());
                        }
                        case "2" -> {
                            System.out.print("Nomor: ");
                            tugas.selesaikan(Integer.parseInt(in.nextLine().trim()));
                        }
                        case "3" -> tugas.cetak();
                        case "4" -> System.out.println(tugas.jumlahSelesai() + " tugas selesai");
                        case "0" -> jalan = false;
                        default -> System.out.println("Menu tidak dikenal");
                    }
                } catch (NumberFormatException e) {
                    System.out.println("Masukkan angka yang benar");
                } catch (IllegalArgumentException e) {
                    System.out.println("Error: " + e.getMessage());
                }
            }
        }
    }
}

Di sini exception ditangani di satu tempat (menu) sehingga program tidak crash karena input salah.

Langkah 4 — menyimpan ke berkas

Paket java.nio.file membuat baca/tulis berkas teks sangat singkat:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

Path berkas = Path.of("tugas.txt");

// Simpan: satu baris per tugas, format  selesai|judul
void simpan(List<Tugas> semua) throws IOException {
    List<String> baris = semua.stream()
            .map(t -> t.selesai() + "|" + t.judul())
            .toList();
    Files.write(berkas, baris);
}

// Muat
List<Tugas> muat() throws IOException {
    if (!Files.exists(berkas)) return List.of();
    return Files.readAllLines(berkas).stream()
            .map(b -> b.split("\\|", 2))
            .map(p -> new Tugas(p[1], Boolean.parseBoolean(p[0])))
            .toList();
}

IOException adalah exception checked, sehingga wajib ditangani (try/catch) atau dideklarasikan (throws). Di aplikasi nyata, tangani dengan pesan ramah: "Gagal menyimpan berkas".

Ide pengembangan

  • Tambahkan enum Prioritas { RENDAH, SEDANG, TINGGI } pada Tugas lalu urutkan dengan Comparator.
  • Tambahkan fitur hapus tugas dan filter "belum selesai".
  • Pecah ke beberapa berkas dan package, lalu bangun dengan Maven atau Gradle.
  • Tulis unit test dengan JUnit 5 untuk DaftarTugas.
  • Langkah belajar berikutnya: Spring Boot untuk membuat REST API, JDBC/JPA untuk database, dan Maven/Gradle untuk manajemen dependensi.

Selamat!

Kamu sudah menempuh perjalanan dari "Hello World" sampai aplikasi lengkap. Latihan terakhir ini merangkum inti proyek: model data dengan record, daftar di ArrayList, dan statistik dengan Stream. Setelah itu, kerjakan quiz akhir untuk meraih sertifikat.

Praktikkan langsung, gratis

Tulis dan jalankan kode langsung di browser, dapatkan penilaian otomatis. Daftar gratis kapan saja untuk menyimpan progres dan meraih sertifikat.

Coba latihan sekarang, tanpa daftar
Bagikan: WhatsApp Facebook LinkedIn X