Giải Bài Candidate Management System – Java OOP (LAB211 – FPT)

Hướng dẫn giải bài Candidate Management Java – lab211 FPT: quản lý ứng viên, OOP, kế thừa class, validation, ArrayList, tìm kiếm theo loại.

Giới thiệu bài lab

Hello anh em! Nếu bạn đang học môn LAB211 – OOP with Java tại FPT hoặc đơn giản là muốn luyện tập Java hướng đối tượng cho cứng tay, thì bài “Candidate Management System” chính là một món ăn không thể thiếu trong thực đơn luyện code. Bài này vừa giúp ôn tập kiến thức về kế thừa, quản lý danh sách bằng ArrayList, vừa rèn kỹ năng xử lý dữ liệu đầu vào và xây dựng chương trình Java Console một cách bài bản. Bên dưới mình có chia sẻ source code của bài tập này, tuy nhiên chỉ mang tính chất tham khảo bởi vì giảng viên có thể yêu cầu bạn thay đổi code cho phù hợp (tùy từng thời điểm).

Mục tiêu chính của bài lab

  • Xây dựng một chương trình Java console để quản lý thông tin ứng viên cho phòng nhân sự (HR)
  • Ứng dụng kiến thức về:
    • Lập trình hướng đối tượng (OOP)
    • Kế thừa class (Candidate là class cha, 3 class con kế thừa)
    • Kiểm tra đầu vào (Validation): năm sinh, số điện thoại, email,…
    • Quản lý danh sách bằng ArrayList
    • Tìm kiếm ứng viên theo tên và loại

Yêu cầu kỹ thuật

  • Ngôn ngữ: Java
  • Kiểu ứng dụng: Console Application
  • Không dùng thư viện ngoài – chỉ sử dụng core Java
  • Áp dụng đầy đủ 4 tính chất OOP (đặc biệt là inheritance, override)

Bối cảnh bài toán

Công ty cần một hệ thống đơn giản để quản lý các ứng viên phục vụ tuyển dụng. Các ứng viên được chia thành 3 nhóm:

  1. Experience – người đã có kinh nghiệm đi làm
  2. Fresher – người vừa tốt nghiệp
  3. Intern – sinh viên thực tập

Tất cả ứng viên đều có một số thông tin chung (họ tên, năm sinh, địa chỉ, email, v.v.) và mỗi nhóm sẽ có các thuộc tính riêng biệt. Hệ thống sẽ cho phép người dùng:

  • Nhập thông tin ứng viên
  • Kiểm tra tính hợp lệ của dữ liệu
  • Tìm kiếm ứng viên theo tên và loại

Vì sao bài này quan trọng?

  • Đây là bài lab cốt lõi của LAB211, được dùng để kiểm tra mức độ hiểu và vận dụng OOP thực tế.
  • Nếu bạn nắm chắc bài này, bạn sẽ thấy việc làm các bài thực hành sau dễ hơn rất nhiều.
  • Khi đi phỏng vấn fresher Java, những bài như thế này cực kỳ hữu ích để kể lại kinh nghiệm học tập và thực hành.

Đề bài gốc – Candidate Management System (LAB211)

Title

Create a Java console program to manage Candidates of company.

Background Context

Candidate management system project in Java is basically developed to manage the candidates of HR (Human Resource) department. In every company, candidate management is very important and it is not easy to handle it manually. So, a candidate management system project is made to be computerized. By computerizing the system, it becomes possible to overcome manual problems and increase efficiency.

Program Specifications

Candidate management system includes some functions are work for creating, updating, deleting as well as searching. Create three classes with three kinds of candidate: Experience, Fresher, Intern

All Candidates have common attributes: CandidateId, FirstName, LastName, BirthDate, Address, Phone, Email andCandidatetype. There are three value of candidate type:

  • 0: for Experience
  • 1: for Fresher candidate
  • 2: for Intern candidate

However, each kind of candidate has addition different attributes:

  • Experience candidate: year of experience (ExpInYear), Professional Skill (ProSkill).
  • Freshercandidate has addition attributes: graduated time (Graduation_date), Rank of Graduation (Graduation_rank) and university where student graduated (Education)
  • Intern candidate: Majors, Semester, Universityname

Main Screen

CANDIDATE MANAGEMENT SYSTEM
1. Experience
2. Fresher
3. Internship
4. Searching
5. Exit
Please choose:

Function details:

Create Candidate and store inArrayList.

Requirements:

  • The program have to check valid data for: Date of Birth, Phone, Email, Year of Experience, Rankof Graduation.
    • BirthDate : is number with length is 4 character (1900...Current Year)
    • Phone: is number with minimum 10 characters
    • Email: with format <account name>@<domain>. (eg: khanhvh@fe.edu.vn)
    • Year of Experience : is number from 0 to 100
    • Rank of Graduation: with one of 4 values (Excellence, Good, Fair, Poor)
  • From “Main Screen”, use select one item (1,2,3) to create candidate. After each candidate is created, the system shows message: Do you want to order now (Y/N)?. User chooses Y to continues, if you chooses N, the program returns main screen and display all candidates who are created.
Search function

  • User select item 4, the program displays all candidates and requires user inputting Candidate name (First Name or Last Name) and type of candidate. The program will search and display result with: Candidate name (FirstName + LastName), BirthDate, Address, Phone, Email andCandidatetype. For example:
List of candidate:
===========EXPERIENCE CANDIDATE============
Aelbrecht Stefan
Aguirre Eva
Ahlgren Maria
Antosova Adeleva

==========FRESHER CANDIDATE==============
Barbosa De Souza
Cabrera Cornide
Calderon Cuevas
Casulari Motta

===========INTERN CANDIDATE==============
Maria Madeleine
Csokan Babett
Joana Filipa
Patricia Carine

Input Candidate name (First name or Last name): eva
Input type of candidate: 0

The candidates found:
+---+----------------+---------+-------------+----------+-----------------+----+
|No.|Fullname        |Birthdate|Address      |Phone     |Email            |Type|
+---+----------------+---------+-------------+----------+-----------------+----+
| 1 |Aguirre Eva     | 1990    |Sao paulo    |0940394275|eva@asante.com   | 0  |
| 2 |Antosova Adeleva| 1989    |Rio de janero|0984933668|adelave@janeo.com| 0  |

Technical Requirements

  • Use Object-Oriented programming style: inheritance
  • Use only core Java functions and classes (no external libraries)

Guidelines

Slot Task Description
1 - Code Design
- Create Experience Candidate
Should create Candidate as a SuperClass.
Experience, Fresher and Internship Candidate as SubClasses that extend Candidate Should
2 - Create Fresher Candidate Should use ArrayList to store Fresher Candidate
3 - Create Intern Candidate Should use ArrayList to store Intern Candidate
4 - Search candidate
5 - Review program

Source Code – Full Project (Java)

📁 Candidate.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package se1905l01;

/**
 * L01 - Create a Java console program to manage Candidates of company.
 *
 * @author TruongNTCE180140
 */
public class Candidate {

    protected String candidateId;    // Candidate ID
    protected String firstName;      // First name of the candidate
    protected String lastName;       // Last name of the candidate
    protected int birthDate;         // Birth date (year)
    protected String address;        // Address of the candidate
    protected String phone;          // Phone number of the candidate
    protected String email;          // Email of the candidate
    protected int candidateType;     // Type of candidate (0: Experience, 1: Fresher, 2: Intern)

    /**
     * Constructor to initialize candidate details.
     *
     * @param candidateId Candidate ID.
     * @param firstName First name of the candidate.
     * @param lastName Last name of the candidate.
     * @param birthDate Birth date of the candidate.
     * @param address Address of the candidate.
     * @param phone Phone number of the candidate.
     * @param email Email of the candidate.
     * @param candidateType Type of candidate (0: Experience, 1: Fresher, 2:
     * Intern).
     */
    public Candidate(String candidateId, String firstName, String lastName, int birthDate, String address, String phone, String email, int candidateType) {
        this.candidateId = candidateId;
        this.firstName = firstName;
        this.lastName = lastName;
        this.birthDate = birthDate;
        this.address = address;
        this.phone = phone;
        this.email = email;
        this.candidateType = candidateType;
    }

    // Getter and Setter Methods for all attributes
    /**
     * Get the candidate ID.
     *
     * @return Candidate ID.
     */
    public String getCandidateId() {
        return candidateId;
    }

    /**
     * Set the candidate ID.
     *
     * @param candidateId Candidate ID to set.
     */
    public void setCandidateId(String candidateId) {
        this.candidateId = candidateId;
    }

    /**
     * Get the first name of the candidate.
     *
     * @return First name of the candidate.
     */
    public String getFirstName() {
        return firstName;
    }

    /**
     * Set the first name of the candidate.
     *
     * @param firstName First name to set.
     */
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    /**
     * Get the last name of the candidate.
     *
     * @return Last name of the candidate.
     */
    public String getLastName() {
        return lastName;
    }

    /**
     * Set the last name of the candidate.
     *
     * @param lastName Last name to set.
     */
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    /**
     * Get the birth date of the candidate.
     *
     * @return Birth date of the candidate.
     */
    public int getBirthDate() {
        return birthDate;
    }

    /**
     * Set the birth date of the candidate.
     *
     * @param birthDate Birth date to set.
     */
    public void setBirthDate(int birthDate) {
        this.birthDate = birthDate;
    }

    /**
     * Get the address of the candidate.
     *
     * @return Address of the candidate.
     */
    public String getAddress() {
        return address;
    }

    /**
     * Set the address of the candidate.
     *
     * @param address Address to set.
     */
    public void setAddress(String address) {
        this.address = address;
    }

    /**
     * Get the phone number of the candidate.
     *
     * @return Phone number of the candidate.
     */
    public String getPhone() {
        return phone;
    }

    /**
     * Set the phone number of the candidate.
     *
     * @param phone Phone number to set.
     */
    public void setPhone(String phone) {
        this.phone = phone;
    }

    /**
     * Get the email of the candidate.
     *
     * @return Email of the candidate.
     */
    public String getEmail() {
        return email;
    }

    /**
     * Set the email of the candidate.
     *
     * @param email Email to set.
     */
    public void setEmail(String email) {
        this.email = email;
    }

    /**
     * Get the candidate type (0 for Experience, 1 for Fresher, 2 for Intern).
     *
     * @return Candidate type.
     */
    public int getCandidateType() {
        return candidateType;
    }

    /**
     * Set the candidate type (0 for Experience, 1 for Fresher, 2 for Intern).
     *
     * @param candidateType Candidate type to set.
     */
    public void setCandidateType(int candidateType) {
        this.candidateType = candidateType;
    }

    /**
     * Method to get the full name of the candidate.
     *
     * @return Full name (First name + Last name).
     */
    public String getFullName() {
        return firstName + " " + lastName;
    }

    /**
     * Method to display detailed information of the candidate. This method
     * prints the candidate's full name, birth date, address, phone number,
     * email, and candidate type in a formatted manner.
     *
     * @param name Full name of the candidate.
     */
    public void printDetails() {
        System.out.printf("| %-15s | %-10d | %-10s | %-10s | %-10s | %-10s | %-10d |\n",
                getFullName(), birthDate, address, phone, email, candidateType);
    }
}
📁 CandidateManagement.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package se1905l01;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

/**
 * L01 - Create a Java console program to manage Candidates of company.
 *
 * @author TruongNTCE180140
 */
public class CandidateManagement {

    private ArrayList<Candidate> candidates = new ArrayList<>(); // List to store candidates
    private Scanner sc = new Scanner(System.in); // Scanner for user input
    private ValidationHelper validator = new ValidationHelper(); // Validator for input validation

    /**
     * Shows the list of Experience candidates.
     */
    public void showExperienceCandidates() {
        List<Candidate> experienceCandidates = new ArrayList<>();
        for (Candidate candidate : candidates) {
            if (candidate instanceof Experience) {
                experienceCandidates.add(candidate);
            }
        }
        if (!experienceCandidates.isEmpty()) {
            System.out.println("===========EXPERIENCE CANDIDATE============");
            for (Candidate candidate : experienceCandidates) {
                System.out.println(candidate.getFullName());
                System.out.println();
            }
        }
    }

    /**
     * Shows the list of Fresher candidates.
     */
    public void showFresherCandidates() {
        List<Candidate> fresherCandidates = new ArrayList<>();
        for (Candidate candidate : candidates) {
            if (candidate instanceof Fresher) {
                fresherCandidates.add(candidate);
            }
        }
        if (!fresherCandidates.isEmpty()) {
            System.out.println("==========FRESHER CANDIDATE==============");
            for (Candidate candidate : fresherCandidates) {
                System.out.println(candidate.getFullName());
                System.out.println();
            }
        }
    }

    /**
     * Shows the list of Intern candidates.
     */
    public void showInternCandidates() {
        List<Candidate> internCandidates = new ArrayList<>();
        for (Candidate candidate : candidates) {
            if (candidate instanceof Intern) {
                internCandidates.add(candidate);
            }
        }
        if (!internCandidates.isEmpty()) {
            System.out.println("===========INTERN CANDIDATE==============");
            for (Candidate candidate : internCandidates) {
                System.out.println(candidate.getFullName());
                System.out.println();
            }
        }
    }

    /**
     * Shows all candidates by calling respective methods for each type.
     */
    public void showCandidateList() {
        if (!candidates.isEmpty()) {
            showExperienceCandidates();
            showFresherCandidates();
            showInternCandidates();
        }
    }

    /**
     * Creates an Experience candidate by collecting and validating user input.
     */
    public void createExperienceCandidate() {
        // Get and validate candidate ID
        String candidateId;
        do {
            System.out.print("Enter candidate ID: ");
            candidateId = sc.nextLine();
            if (!validator.isValidId(candidateId)) {
                System.out.println("Invalid input. Please enter letters and numbers only.");
            } else if (validator.isExisted(candidateId, candidates)) {
                System.out.println("This ID already exists. Please enter a different one.");
            }
        } while (!validator.isValidId(candidateId) || validator.isExisted(candidateId, candidates));

        // Get and validate first name
        String firstName;
        do {
            System.out.print("Enter first name: ");
            firstName = sc.nextLine();
            if (!validator.isValidName(firstName)) {
                System.out.println("Invalid input. Please enter letters and spaces only.");
            }
        } while (!validator.isValidName(firstName));

        // Get and validate last name
        String lastName;
        do {
            System.out.print("Enter last name: ");
            lastName = sc.nextLine();
            if (!validator.isValidName(lastName)) {
                System.out.println("Invalid input. Please enter letters and spaces only.");
            }
        } while (!validator.isValidName(lastName));

        // Get and validate birth year
        int birthDate;
        do {
            System.out.print("Enter birth year: ");
            String birthDateStr = sc.nextLine();
            while (!validator.isValidInteger(birthDateStr)) {
                System.out.print("Invalid input. Please enter a valid year: ");
                birthDateStr = sc.nextLine();
            }
            birthDate = Integer.parseInt(birthDateStr);
            if (!validator.isValidBirthDateForExperience(birthDate)) {
                System.out.println("Invalid input. Experience candidates must be at least 23 years old.");
            }
        } while (!validator.isValidBirthDateForExperience(birthDate));

        // Get and validate address
        String address;
        do {
            System.out.print("Enter address: ");
            address = sc.nextLine();
            if (!validator.isValidAddress(address)) {
                System.out.println("Invalid input. Address cannot be empty.");
            }
        } while (!validator.isValidAddress(address));

        // Get and validate phone number
        String phone;
        do {
            System.out.print("Enter phone: ");
            phone = sc.nextLine();
            if (!validator.isValidPhone(phone)) {
                System.out.println("Invalid input. Please enter a valid Vietnamese phone number.");
            }
        } while (!validator.isValidPhone(phone));

        // Get and validate email
        String email;
        do {
            System.out.print("Enter email: ");
            email = sc.nextLine();
            if (!validator.isValidEmail(email)) {
                System.out.println("Invalid input. Please enter a valid email address.");
            }
        } while (!validator.isValidEmail(email));

        // Get and validate years of experience
        int expInYear = 0;
        boolean validInput = false;
        do {
            System.out.print("Enter years of experience: ");
            String expInYearStr = sc.nextLine();

            if (!validator.isValidInteger(expInYearStr)) {
                System.out.println("Invalid input. Please enter a valid number.");
                continue;
            }

            expInYear = Integer.parseInt(expInYearStr);
            if (!validator.isValidExperienceYears(expInYear, birthDate)) {
                System.out.println("Invalid input. Years of experience must be between 0 and "
                        + (Calendar.getInstance().get(Calendar.YEAR) - birthDate - 22) + ".");
            } else {
                validInput = true;
            }
        } while (!validInput);

        // Get and validate professional skill
        String proSkill;
        do {
            System.out.print("Enter professional skill: ");
            proSkill = sc.nextLine();
            if (!validator.isValidName(proSkill)) {
                System.out.println("Invalid input. Professional skill can only contain letters and spaces.");
            }
        } while (!validator.isValidName(proSkill));

        // Add the new Experience candidate
        candidates.add(new Experience(candidateId, firstName, lastName, birthDate,
                address, phone, email, 0, expInYear, proSkill));

        if (askToContinue()) {
            showExperienceCandidates();
            createExperienceCandidate();
        }
    }

    /**
     * Creates a Fresher candidate by collecting and validating user input.
     */
    public void createFresherCandidate() {
        // Get and validate candidate ID
        String candidateId;
        do {
            System.out.print("Enter candidate ID: ");
            candidateId = sc.nextLine();
            if (!validator.isValidId(candidateId)) {
                System.out.println("Invalid input. Please enter letters and numbers only.");
            } else if (validator.isExisted(candidateId, candidates)) {
                System.out.println("This ID already exists. Please enter a different one.");
            }
        } while (!validator.isValidId(candidateId) || validator.isExisted(candidateId, candidates));

        // Get and validate first name
        String firstName;
        do {
            System.out.print("Enter first name: ");
            firstName = sc.nextLine();
            if (!validator.isValidName(firstName)) {
                System.out.println("Invalid input. Please enter letters and spaces only.");
            }
        } while (!validator.isValidName(firstName));

        // Get and validate last name
        String lastName;
        do {
            System.out.print("Enter last name: ");
            lastName = sc.nextLine();
            if (!validator.isValidName(lastName)) {
                System.out.println("Invalid input. Please enter letters and spaces only.");
            }
        } while (!validator.isValidName(lastName));

        // Get and validate birth year
        int birthDate;
        do {
            System.out.print("Enter birth year: ");
            String birthDateStr = sc.nextLine();
            while (!validator.isValidInteger(birthDateStr)) {
                System.out.print("Invalid input. Please enter a valid year: ");
                birthDateStr = sc.nextLine();
            }
            birthDate = Integer.parseInt(birthDateStr);
            if (!validator.isValidBirthDateForFresher(birthDate)) {
                System.out.println("Invalid input. Fresher candidates must be at least 22 years old.");
            }
        } while (!validator.isValidBirthDateForFresher(birthDate));

        // Get and validate address
        String address;
        do {
            System.out.print("Enter address: ");
            address = sc.nextLine();
            if (!validator.isValidAddress(address)) {
                System.out.println("Invalid input. Address cannot be empty.");
            }
        } while (!validator.isValidAddress(address));

        // Get and validate phone number
        String phone;
        do {
            System.out.print("Enter phone: ");
            phone = sc.nextLine();
            if (!validator.isValidPhone(phone)) {
                System.out.println("Invalid input. Please enter a valid Vietnamese phone number.");
            }
        } while (!validator.isValidPhone(phone));

        // Get and validate email
        String email;
        do {
            System.out.print("Enter email: ");
            email = sc.nextLine();
            if (!validator.isValidEmail(email)) {
                System.out.println("Invalid input. Please enter a valid email address.");
            }
        } while (!validator.isValidEmail(email));

        // Get and validate graduation year
        int graduationDate;
        do {
            System.out.print("Enter graduation year: ");
            String graduationDateStr = sc.nextLine();
            while (!validator.isValidInteger(graduationDateStr)) {
                System.out.print("Invalid input. Please enter a valid year: ");
                graduationDateStr = sc.nextLine();
            }
            graduationDate = Integer.parseInt(graduationDateStr);
            if (!validator.isValidGraduationYear(graduationDate, birthDate)) {
                System.out.println("Invalid input. Graduation year must be between "
                        + (birthDate + 18) + " and current year.");
            }
        } while (!validator.isValidGraduationYear(graduationDate, birthDate));

        // Get and validate graduation rank
        String graduationRank;
        do {
            System.out.print("Enter rank of graduation (Excellence, Good, Fair, Poor): ");
            graduationRank = sc.nextLine();
            if (!validator.isValidGraduationRank(graduationRank)) {
                System.out.println("Invalid input. Please enter one of: Excellence, Good, Fair, Poor");
            }
        } while (!validator.isValidGraduationRank(graduationRank));

        // Get and validate university name
        String universityName;
        do {
            System.out.print("Enter university name: ");
            universityName = sc.nextLine();
            if (!validator.isValidName(universityName)) {
                System.out.println("Invalid input. University name can only contain letters and spaces.");
            }
        } while (!validator.isValidName(universityName));

        // Add the new Fresher candidate
        candidates.add(new Fresher(candidateId, firstName, lastName, birthDate,
                address, phone, email, 1, graduationDate, graduationRank, universityName));

        if (askToContinue()) {
            showFresherCandidates();
            createFresherCandidate();
        }
    }

    /**
     * Creates an Intern candidate by collecting and validating user input.
     */
    public void createInternCandidate() {
        // Get and validate candidate ID
        String candidateId;
        do {
            System.out.print("Enter candidate ID: ");
            candidateId = sc.nextLine();
            if (!validator.isValidId(candidateId)) {
                System.out.println("Invalid input. Please enter letters and numbers only.");
            } else if (validator.isExisted(candidateId, candidates)) {
                System.out.println("This ID already exists. Please enter a different one.");
            }
        } while (!validator.isValidId(candidateId) || validator.isExisted(candidateId, candidates));

        // Get and validate first name
        String firstName;
        do {
            System.out.print("Enter first name: ");
            firstName = sc.nextLine();
            if (!validator.isValidName(firstName)) {
                System.out.println("Invalid input. Please enter letters and spaces only.");
            }
        } while (!validator.isValidName(firstName));

        // Get and validate last name
        String lastName;
        do {
            System.out.print("Enter last name: ");
            lastName = sc.nextLine();
            if (!validator.isValidName(lastName)) {
                System.out.println("Invalid input. Please enter letters and spaces only.");
            }
        } while (!validator.isValidName(lastName));

        // Get and validate birth year
        int birthDate;
        do {
            System.out.print("Enter birth year: ");
            String birthDateStr = sc.nextLine();
            while (!validator.isValidInteger(birthDateStr)) {
                System.out.print("Invalid input. Please enter a valid year: ");
                birthDateStr = sc.nextLine();
            }
            birthDate = Integer.parseInt(birthDateStr);
            if (!validator.isValidBirthDateForIntern(birthDate)) {
                System.out.println("Invalid input. Intern candidates must be at least 21 years old.");
            }
        } while (!validator.isValidBirthDateForIntern(birthDate));

        // Get and validate address
        String address;
        do {
            System.out.print("Enter address: ");
            address = sc.nextLine();
            if (!validator.isValidAddress(address)) {
                System.out.println("Invalid input. Address cannot be empty.");
            }
        } while (!validator.isValidAddress(address));

        // Get and validate phone number
        String phone;
        do {
            System.out.print("Enter phone: ");
            phone = sc.nextLine();
            if (!validator.isValidPhone(phone)) {
                System.out.println("Invalid input. Please enter a valid Vietnamese phone number.");
            }
        } while (!validator.isValidPhone(phone));

        // Get and validate email
        String email;
        do {
            System.out.print("Enter email: ");
            email = sc.nextLine();
            if (!validator.isValidEmail(email)) {
                System.out.println("Invalid input. Please enter a valid email address.");
            }
        } while (!validator.isValidEmail(email));

        // Get and validate major
        String major;
        do {
            System.out.print("Enter major: ");
            major = sc.nextLine();
            if (!validator.isValidMajor(major)) {
                System.out.println("Invalid input. Major can only contain letters and spaces.");
            }
        } while (!validator.isValidMajor(major));

        // Get and validate semester
        String semester;
        do {
            System.out.print("Enter semester: ");
            semester = sc.nextLine();
            if (!validator.isValidNonEmpty(semester)) {
                System.out.println("Invalid input. Semester cannot be empty.");
            }
        } while (!validator.isValidNonEmpty(semester));

        // Get and validate university name
        String universityName;
        do {
            System.out.print("Enter university name: ");
            universityName = sc.nextLine();
            if (!validator.isValidName(universityName)) {
                System.out.println("Invalid input. University name can only contain letters and spaces.");
            }
        } while (!validator.isValidName(universityName));

        // Add the new Intern candidate
        candidates.add(new Intern(candidateId, firstName, lastName, birthDate,
                address, phone, email, 2, major, semester, universityName));

        if (askToContinue()) {
            showInternCandidates();
            createInternCandidate();
        }
    }

    /**
     * Displays candidates in a formatted table.
     *
     * @param candidates List of candidates to display.
     */
    private void displayCandidateTable(List<Candidate> candidates) {
        System.out.println("+---+------------------------+----------+-------------------+------------+---------------------+-------------+");
        System.out.println("|No.| Fullname               | Birthdate| Address           | Phone      | Email               |    Type     |");
        System.out.println("+---+------------------------+----------+-------------------+------------+---------------------+-------------+");

        int index = 1;
        for (Candidate candidate : candidates) {
            String type = candidate instanceof Experience ? "Experience"
                    : candidate instanceof Fresher ? "Fresher" : "Intern";

            System.out.printf("|%3d| %-23s| %9s| %-18s| %11s| %-20s| %-4s|\n",
                    index++,
                    candidate.getFullName(),
                    candidate.getBirthDate(),
                    candidate.getAddress(),
                    candidate.getPhone(),
                    candidate.getEmail(),
                    type);
        }
        System.out.println("+---+------------------------+----------+-------------------+------------+---------------------+-------------+");
    }

    /**
     * Handles candidate search operations by allowing user to input a search
     * key.
     */
    public void searchCandidates() {
        System.out.print("Input search key: ");
        String searchKey = sc.nextLine().toLowerCase();

        List<Candidate> foundCandidates = candidates.stream()
                .filter(c -> c.getCandidateId().toLowerCase().contains(searchKey)
                || c.getFullName().toLowerCase().contains(searchKey)
                || c.getPhone().contains(searchKey)
                || c.getEmail().toLowerCase().contains(searchKey)
                || c.getAddress().toLowerCase().contains(searchKey)
                || (c instanceof Experience && "experience".contains(searchKey))
                || (c instanceof Fresher && "fresher".contains(searchKey))
                || (c instanceof Intern && "intern".contains(searchKey)))
                .collect(Collectors.toList());

        if (!foundCandidates.isEmpty()) {
            System.out.println("\nThe candidates found:");
            displayCandidateTable(foundCandidates);
        } else {
            System.out.println("No candidates found with the search key: " + searchKey);
        }
    }

    /**
     * Helper method to ask if the user wants to continue adding candidates.
     *
     * @return true if the user wants to continue, false otherwise.
     */
    private boolean askToContinue() {
        String choiceStr;
        do {
            System.out.print("\nDo you want to continue to add more candidates? (Y/N): ");
            choiceStr = sc.nextLine();
            if (!choiceStr.equalsIgnoreCase("Y") && !choiceStr.equalsIgnoreCase("N")) {
                System.out.println("Invalid input. Please enter Y or N.");
            }
        } while (!choiceStr.equalsIgnoreCase("Y") && !choiceStr.equalsIgnoreCase("N"));

        if (choiceStr.equalsIgnoreCase("N")) {
            System.out.println("\nList of candidates:");
        }

        return choiceStr.equalsIgnoreCase("Y");
    }

    /**
     * Main menu of the application that allows user to choose actions.
     */
    public void mainMenu() {
        while (true) {
            showCandidateList();

            System.out.println("CANDIDATE MANAGEMENT SYSTEM");
            System.out.println("1. Experience");
            System.out.println("2. Fresher");
            System.out.println("3. Internship");
            System.out.println("4. Searching");
            System.out.println("5. Exit");
            System.out.print("Please choose: ");

            String choiceStr = sc.nextLine();
            while (!validator.isValidInteger(choiceStr)) {
                System.out.print("Invalid input. Please enter a number from 1 - 5! ");
                choiceStr = sc.nextLine();
            }

            switch (Integer.parseInt(choiceStr)) {
                case 1:
                    createExperienceCandidate();
                    break;
                case 2:
                    createFresherCandidate();
                    break;
                case 3:
                    createInternCandidate();
                    break;
                case 4:
                    searchCandidates();
                    break;
                case 5:
                    System.out.println("Exiting system. Goodbye!");
                    return;
                default:
                    System.out.println("Invalid choice. Please select again!");
            }
        }
    }
}
📁 Experience.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package se1905l01;

/**
 * L01 - Create a Java console program to manage Candidates of company.
 *
 * @author TruongNTCE180140
 */
public class Experience extends Candidate {

    private int yearsOfExperience; // Years of experience
    private String professionalSkill; // Professional skills

    /**
     * Constructor for the Experience class.
     *
     * @param candidateId The candidate's ID.
     * @param firstName The candidate's first name.
     * @param lastName The candidate's last name.
     * @param birthDate The candidate's birth year.
     * @param address The candidate's address.
     * @param phone The candidate's phone number.
     * @param email The candidate's email.
     * @param candidateType The type of the candidate (0 for Experience).
     * @param yearsOfExperience The number of years of experience.
     * @param professionalSkill The professional skills of the candidate.
     */
    public Experience(String candidateId, String firstName, String lastName, int birthDate, String address,
            String phone, String email, int candidateType, int yearsOfExperience, String professionalSkill) {
        // Call the parent constructor to initialize the common attributes
        super(candidateId, firstName, lastName, birthDate, address, phone, email, candidateType);
        this.yearsOfExperience = yearsOfExperience;
        this.professionalSkill = professionalSkill;
    }

    // Getter and Setter Methods for Experience class attributes
    /**
     * Get the number of years of experience.
     *
     * @return Years of experience.
     */
    public int getYearsOfExperience() {
        return yearsOfExperience;
    }

    /**
     * Set the number of years of experience.
     *
     * @param yearsOfExperience Years of experience to set.
     */
    public void setYearsOfExperience(int yearsOfExperience) {
        this.yearsOfExperience = yearsOfExperience;
    }

    /**
     * Get the professional skill of the candidate.
     *
     * @return Professional skill.
     */
    public String getProfessionalSkill() {
        return professionalSkill;
    }

    /**
     * Set the professional skill of the candidate.
     *
     * @param professionalSkill Professional skill to set.
     */
    public void setProfessionalSkill(String professionalSkill) {
        this.professionalSkill = professionalSkill;
    }

    /**
     * Method to display detailed information for an experienced candidate. This
     * method overrides the printDetails method from the Candidate class to
     * include specific details for experienced candidates.
     */
    @Override
    public void printDetails() {
        super.printDetails();  // Print common candidate details
        System.out.printf("| %-10d | %-15s |\n", yearsOfExperience, professionalSkill); // Print specific experience details
    }
}
📁 Fresher.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package se1905l01;

/**
 * L01 - Create a Java console program to manage Candidates of company.
 *
 * @author TruongNTCE180140
 */
public class Fresher extends Candidate {

    private int graduationYear; // Graduation year
    private String graduationRank; // Graduation rank
    private String education; // Education institution name

    /**
     * Constructor for the Fresher class.
     *
     * @param candidateId The candidate's ID.
     * @param firstName The candidate's first name.
     * @param lastName The candidate's last name.
     * @param birthDate The candidate's birth year.
     * @param address The candidate's address.
     * @param phone The candidate's phone number.
     * @param email The candidate's email.
     * @param candidateType The type of the candidate (1 for Fresher).
     * @param graduationYear The year of graduation.
     * @param graduationRank The graduation rank (e.g., Excellent, Good).
     * @param education The name of the university or educational institution.
     */
    public Fresher(String candidateId, String firstName, String lastName, int birthDate, String address,
            String phone, String email, int candidateType, int graduationYear, String graduationRank, String education) {
        // Call the parent constructor to initialize the common attributes
        super(candidateId, firstName, lastName, birthDate, address, phone, email, candidateType);
        this.graduationYear = graduationYear;
        this.graduationRank = graduationRank;
        this.education = education;
    }

    // Getter and Setter Methods for Fresher class attributes
    /**
     * Get the graduation year.
     *
     * @return Graduation year.
     */
    public int getGraduationYear() {
        return graduationYear;
    }

    /**
     * Set the graduation year.
     *
     * @param graduationYear Graduation year to set.
     */
    public void setGraduationYear(int graduationYear) {
        this.graduationYear = graduationYear;
    }

    /**
     * Get the graduation rank.
     *
     * @return Graduation rank.
     */
    public String getGraduationRank() {
        return graduationRank;
    }

    /**
     * Set the graduation rank.
     *
     * @param graduationRank Graduation rank to set.
     */
    public void setGraduationRank(String graduationRank) {
        this.graduationRank = graduationRank;
    }

    /**
     * Get the name of the university.
     *
     * @return University name.
     */
    public String getEducation() {
        return education;
    }

    /**
     * Set the name of the university.
     *
     * @param education University name to set.
     */
    public void setEducation(String education) {
        this.education = education;
    }

    /**
     * Method to display detailed information for a fresher candidate. This
     * method overrides the printDetails method from the Candidate class to
     * include specific details for fresher candidates.
     */
    @Override
    public void printDetails() {
        super.printDetails();  // Print common candidate details
        System.out.printf("| %-10d | %-15s | %-15s |\n", graduationYear, graduationRank, education); // Print specific fresher details
    }
}
📁 Intern.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package se1905l01;

/**
 * L01 - Create a Java console program to manage Candidates of company.
 *
 * @author TruongNTCE180140
 */
public class Intern extends Candidate {

    private String major; // Candidate's major
    private String semester; // Candidate's current semester
    private String universityName; // Name of the university

    /**
     * Constructor for the Intern class.
     *
     * @param candidateId The candidate's ID.
     * @param firstName The candidate's first name.
     * @param lastName The candidate's last name.
     * @param birthDate The candidate's birth year.
     * @param address The candidate's address.
     * @param phone The candidate's phone number.
     * @param email The candidate's email.
     * @param candidateType The type of the candidate (2 for Intern).
     * @param major The candidate's major.
     * @param semester The candidate's current semester.
     * @param universityName The name of the university the candidate is
     * attending.
     */
    public Intern(String candidateId, String firstName, String lastName, int birthDate, String address,
            String phone, String email, int candidateType, String major, String semester, String universityName) {
        // Call the parent constructor to initialize the common attributes
        super(candidateId, firstName, lastName, birthDate, address, phone, email, candidateType);
        this.major = major;
        this.semester = semester;
        this.universityName = universityName;
    }

    // Getter and Setter Methods for Intern class attributes
    /**
     * Get the major of the intern.
     *
     * @return Major.
     */
    public String getMajor() {
        return major;
    }

    /**
     * Set the major of the intern.
     *
     * @param major Major to set.
     */
    public void setMajor(String major) {
        this.major = major;
    }

    /**
     * Get the current semester of the intern.
     *
     * @return Semester.
     */
    public String getSemester() {
        return semester;
    }

    /**
     * Set the current semester of the intern.
     *
     * @param semester Semester to set.
     */
    public void setSemester(String semester) {
        this.semester = semester;
    }

    /**
     * Get the name of the university.
     *
     * @return University name.
     */
    public String getUniversityName() {
        return universityName;
    }

    /**
     * Set the name of the university.
     *
     * @param universityName University name to set.
     */
    public void setUniversityName(String universityName) {
        this.universityName = universityName;
    }

    /**
     * Method to display detailed information for an intern candidate. This
     * method overrides the printDetails method from the Candidate class to
     * include specific details for intern candidates.
     */
    @Override
    public void printDetails() {
        super.printDetails();  // Print common candidate details
        System.out.printf("| %-15s | %-10s | %-15s |\n", major, semester, universityName); // Print specific intern details
    }
}
📁 ValidationHelper.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package se1905l01;

import java.util.Calendar;
import java.util.List;

/**
 * L01 - Create a Java console program to manage Candidates of company.
 *
 * @author TruongNTCE180140
 */
public class ValidationHelper {

    private List<Candidate> candidates; // A list to store candidate objects for validation purposes.

    /**
     * Checks if the input string is a valid integer.
     *
     * @param input the input string
     * @return true if the input is a valid integer, otherwise false
     */
    public boolean isValidInteger(String input) {
        try {
            Integer.parseInt(input);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * Validates if the given phone number follows the Vietnamese format.
     *
     * @param phone the phone number to validate
     * @return true if valid, otherwise false
     */
    public boolean isValidPhone(String phone) {
        return phone.matches("^(03|04|05|07|08|09)\\d{8}$");
    }

    /**
     * Validates email format.
     *
     * @param email the email to validate
     * @return true if valid, otherwise false
     */
    public boolean isValidEmail(String email) {
        return email.matches("^[a-zA-Z0-9]+([._+-]?[a-zA-Z0-9]+)*@(?![.-])[a-zA-Z0-9-]+(?<!-)(?:\\.[a-zA-Z0-9-]+(?<!-))*(\\.[a-zA-Z]{2,})$");
    }

    /**
     * Checks if an input is non-empty.
     *
     * @param input the input string
     * @return true if non-empty, otherwise false
     */
    public boolean isValidNonEmpty(String input) {
        return input != null && !input.trim().isEmpty();
    }

    /**
     * Validates candidate ID format.
     *
     * @param id the candidate ID
     * @return true if valid, otherwise false
     */
    public boolean isValidId(String id) {
        return id != null && !id.trim().isEmpty() && id.matches("[A-Za-z0-9]+");
    }

    /**
     * Checks if a given candidate ID already exists in the list.
     *
     * @param id the candidate ID
     * @param candidates list of candidates
     * @return true if ID exists, otherwise false
     */
    public boolean isExisted(String id, List<Candidate> candidates) {
        return candidates.stream()
                .anyMatch(candidate -> candidate.getCandidateId().equalsIgnoreCase(id));
    }

    /**
     * Validates name format (only letters and spaces allowed).
     *
     * @param name the name to validate
     * @return true if valid, otherwise false
     */
    public boolean isValidName(String name) {
        return isValidNonEmpty(name) && name.matches("[A-Za-z ]+");
    }

    /**
     * Validates address.
     *
     * @param address the address to validate
     * @return true if valid, otherwise false
     */
    public boolean isValidAddress(String address) {
        return isValidNonEmpty(address);
    }

    /**
     * Validates birth year for Experience candidates (must be at least 23 years
     * old).
     *
     * @param birthDate candidate's birth year
     * @return true if valid, otherwise false
     */
    public boolean isValidBirthDateForExperience(int birthDate) {
        int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        return birthDate >= 1900 && (currentYear - birthDate) >= 23;
    }

    /**
     * Validates birth year for Fresher candidates (must be at least 22 years
     * old).
     *
     * @param birthDate candidate's birth year
     * @return true if valid, otherwise false
     */
    public boolean isValidBirthDateForFresher(int birthDate) {
        int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        return birthDate >= 1900 && (currentYear - birthDate) >= 22;
    }

    /**
     * Validates birth year for Intern candidates (must be at least 21 years
     * old).
     *
     * @param birthDate candidate's birth year
     * @return true if valid, otherwise false
     */
    public boolean isValidBirthDateForIntern(int birthDate) {
        int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        return birthDate >= 1900 && (currentYear - birthDate) >= 21;
    }

    /**
     * Validates graduation year (must not be before candidate turns 18).
     *
     * @param graduationYear the year of graduation
     * @param birthDate the candidate's birth year
     * @return true if valid, otherwise false
     */
    public boolean isValidGraduationYear(int graduationYear, int birthDate) {
        int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        int earliestGraduationYear = birthDate + 18;
        return graduationYear <= currentYear && graduationYear >= earliestGraduationYear;
    }

    /**
     * Validates graduation rank (must be one of predefined values).
     *
     * @param rank graduation rank
     * @return true if valid, otherwise false
     */
    public boolean isValidGraduationRank(String rank) {
        return rank.matches("Excellence|Good|Fair|Poor");
    }

    /**
     * Validates years of experience (must be non-negative and within reasonable
     * range based on birth year).
     *
     * @param expYears years of experience
     * @param birthDate candidate's birth year
     * @return true if valid, otherwise false
     */
    public boolean isValidExperienceYears(int expYears, int birthDate) {
        int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        int age = currentYear - birthDate;
        int maxExperience = age - 22;
        return expYears >= 0 && expYears <= maxExperience;
    }

    /**
     * Validates major (for Intern candidates).
     *
     * @param major the major to validate
     * @return true if valid, otherwise false
     */
    public boolean isValidMajor(String major) {
        return isValidNonEmpty(major) && major.matches("[A-Za-z ]+");
    }

    /**
     * Checks if a candidate ID already exists in the internal list and provides
     * a warning.
     *
     * @param id the candidate ID
     * @return true if ID exists, otherwise false
     */
    private boolean isExisted(String id) {
        for (Candidate candidate : candidates) {
            if (candidate.getCandidateId().equalsIgnoreCase(id)) {
                System.out.println("Candidate ID already exists. Please enter a different ID.");
                return true;
            }
        }
        return false;
    }
}
📁 SE1905L01.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package se1905l01;

/**
 * L01 - Create a Java console program to manage Candidates of company.
 *
 * @author TruongNTCE180140
 */
public class SE1905L01 {

    /**
     * The main method.
     *
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // Create an instance of CandidateManagementSystem to run the program
        CandidateManagement system = new CandidateManagement();

        // Display the main menu
        system.mainMenu();
    }

}

Open Source!
Hãy click vào từng folder để xem được code nhé anh em.

Lời kết

Hy vọng bài chia sẻ này sẽ giúp anh em hiểu rõ hơn cách xây dựng một chương trình Java console theo hướng đối tượng (OOP) – từ việc thiết kế class cha/con, quản lý danh sách bằng ArrayList, đến cách xử lý nhập liệu và tìm kiếm một cách bài bản.

Dù chỉ là một bài lab trong môn học LAB211, nhưng “Candidate Management System” lại là nền tảng cực kỳ quan trọng để rèn luyện tư duy lập trình rõ ràng, sạch sẽ và có cấu trúc. Nếu bạn đang học Java tại FPT hoặc tự luyện Java theo lộ trình backend, thì đừng ngại đọc kỹ, code lại và tùy biến thêm các tính năng để luyện tay nghề.

Chúc anh em code vui, không bug và sớm master Java OOP!

Hẹn gặp lại ở những bài chia sẻ kế tiếp trên blog truongdevs.com nhé!

Post a Comment