Introduction
A Contact Management System is a practical Java project that demonstrates core programming concepts such as object-oriented design, collections, file I/O, user input validation, and CRUD operations (Create, Read, Update, Delete). This console-based application allows users to manage personal or professional contacts with details like name, phone number, email, and address. The system persists data to a file (contacts.csv) for durability across sessions and provides a menu-driven interface for intuitive interaction.
Features
- Add contacts with name, phone, email, and address
- View all contacts in a formatted list
- Search contacts by name or phone number
- Update existing contacts
- Delete contacts
- Save contacts to CSV file on exit
- Load contacts from CSV file on startup
- Input validation for phone numbers and emails
- Menu-driven console interface
Complete Source Code
1. Contact.java – Contact Model Class
// Contact.java public class Contact { private String name; private String phone; private String email; private String address; public Contact(String name, String phone, String email, String address) { this.name = name; this.phone = phone; this.email = email; this.address = address; } // Getters public String getName() { return name; } public String getPhone() { return phone; } public String getEmail() { return email; } public String getAddress() { return address; } // Setters public void setName(String name) { this.name = name; } public void setPhone(String phone) { this.phone = phone; } public void setEmail(String email) { this.email = email; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return String.format("Name: %s%nPhone: %s%nEmail: %s%nAddress: %s%n", name, phone, email, address); } // CSV format: name,phone,email,address public String toCSV() { return String.format("%s,%s,%s,%s", name, phone, email, address); } public static Contact fromCSV(String csvLine) { String[] parts = csvLine.split(",", 4); // Split into 4 parts max if (parts.length == 4) { return new Contact(parts[0], parts[1], parts[2], parts[3]); } return null; } } 2. ContactManager.java – Core Logic Class
// ContactManager.java import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.*; public class ContactManager { private List<Contact> contacts; private static final String FILE_NAME = "contacts.csv"; public ContactManager() { this.contacts = new ArrayList<>(); loadContacts(); } public void addContact(String name, String phone, String email, String address) { contacts.add(new Contact(name, phone, email, address)); System.out.println("Contact added successfully."); } public void viewAllContacts() { if (contacts.isEmpty()) { System.out.println("No contacts found."); return; } for (int i = 0; i < contacts.size(); i++) { System.out.println((i + 1) + ".\n" + contacts.get(i)); } } public void searchContacts(String query) { boolean found = false; query = query.toLowerCase(); for (Contact contact : contacts) { if (contact.getName().toLowerCase().contains(query) || contact.getPhone().contains(query)) { System.out.println(contact); found = true; } } if (!found) { System.out.println("No contacts found matching: " + query); } } public void updateContact(int index, String name, String phone, String email, String address) { if (isValidIndex(index)) { Contact contact = contacts.get(index); contact.setName(name); contact.setPhone(phone); contact.setEmail(email); contact.setAddress(address); System.out.println("Contact updated successfully."); } else { System.out.println("Invalid contact number."); } } public void deleteContact(int index) { if (isValidIndex(index)) { contacts.remove(index); System.out.println("Contact deleted."); } else { System.out.println("Invalid contact number."); } } private boolean isValidIndex(int index) { return index >= 0 && index < contacts.size(); } public void saveContacts() { try (PrintWriter writer = new PrintWriter(new FileWriter(FILE_NAME))) { for (Contact contact : contacts) { writer.println(contact.toCSV()); } System.out.println("Contacts saved to " + FILE_NAME); } catch (IOException e) { System.err.println("Error saving contacts: " + e.getMessage()); } } private void loadContacts() { if (!Files.exists(Paths.get(FILE_NAME))) return; try (BufferedReader reader = new BufferedReader(new FileReader(FILE_NAME))) { String line; while ((line = reader.readLine()) != null) { Contact contact = Contact.fromCSV(line); if (contact != null) { contacts.add(contact); } } System.out.println("Loaded " + contacts.size() + " contacts from " + FILE_NAME); } catch (IOException e) { System.err.println("Error loading contacts: " + e.getMessage()); } } } 3. InputValidator.java – Utility Class for Validation
// InputValidator.java import java.util.regex.Pattern; public class InputValidator { private static final String PHONE_PATTERN = "^\\+?[0-9]{10,15}$"; private static final String EMAIL_PATTERN = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@" + "(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; public static boolean isValidPhone(String phone) { return Pattern.matches(PHONE_PATTERN, phone.trim()); } public static boolean isValidEmail(String email) { return Pattern.matches(EMAIL_PATTERN, email.trim()); } } 4. Main.java – Application Entry Point
// Main.java import java.util.Scanner; public class Main { public static void main(String[] args) { ContactManager manager = new ContactManager(); Scanner scanner = new Scanner(System.in); boolean running = true; System.out.println("=== Contact Management System ==="); while (running) { System.out.println("\nChoose an option:"); System.out.println("1. Add Contact"); System.out.println("2. View All Contacts"); System.out.println("3. Search Contact"); System.out.println("4. Update Contact"); System.out.println("5. Delete Contact"); System.out.println("6. Exit"); System.out.print("Enter your choice: "); String choice = scanner.nextLine().trim(); switch (choice) { case "1": addContact(scanner, manager); break; case "2": manager.viewAllContacts(); break; case "3": searchContact(scanner, manager); break; case "4": updateContact(scanner, manager); break; case "5": deleteContact(scanner, manager); break; case "6": manager.saveContacts(); System.out.println("Goodbye!"); running = false; break; default: System.out.println("Invalid choice. Please enter 1-6."); } } scanner.close(); } private static void addContact(Scanner scanner, ContactManager manager) { System.out.print("Enter name: "); String name = scanner.nextLine().trim(); if (name.isEmpty()) { System.out.println("Name cannot be empty."); return; } System.out.print("Enter phone: "); String phone = scanner.nextLine().trim(); if (!InputValidator.isValidPhone(phone)) { System.out.println("Invalid phone number. Use 10-15 digits (optional + prefix)."); return; } System.out.print("Enter email: "); String email = scanner.nextLine().trim(); if (!email.isEmpty() && !InputValidator.isValidEmail(email)) { System.out.println("Invalid email format."); return; } System.out.print("Enter address: "); String address = scanner.nextLine().trim(); manager.addContact(name, phone, email, address); } private static void searchContact(Scanner scanner, ContactManager manager) { System.out.print("Enter name or phone to search: "); String query = scanner.nextLine().trim(); if (!query.isEmpty()) { manager.searchContacts(query); } else { System.out.println("Search query cannot be empty."); } } private static void updateContact(Scanner scanner, ContactManager manager) { manager.viewAllContacts(); if (manager.contacts.isEmpty()) return; System.out.print("Enter contact number to update: "); if (!scanner.hasNextInt()) { System.out.println("Invalid input. Please enter a number."); scanner.nextLine(); // Clear invalid input return; } int index = scanner.nextInt() - 1; scanner.nextLine(); // Consume newline System.out.print("Enter new name: "); String name = scanner.nextLine().trim(); if (name.isEmpty()) { System.out.println("Name cannot be empty."); return; } System.out.print("Enter new phone: "); String phone = scanner.nextLine().trim(); if (!InputValidator.isValidPhone(phone)) { System.out.println("Invalid phone number."); return; } System.out.print("Enter new email: "); String email = scanner.nextLine().trim(); if (!email.isEmpty() && !InputValidator.isValidEmail(email)) { System.out.println("Invalid email format."); return; } System.out.print("Enter new address: "); String address = scanner.nextLine().trim(); manager.updateContact(index, name, phone, email, address); } private static void deleteContact(Scanner scanner, ContactManager manager) { manager.viewAllContacts(); if (manager.contacts.isEmpty()) return; System.out.print("Enter contact number to delete: "); if (!scanner.hasNextInt()) { System.out.println("Invalid input. Please enter a number."); scanner.nextLine(); // Clear invalid input return; } int index = scanner.nextInt() - 1; scanner.nextLine(); // Consume newline manager.deleteContact(index); } } How It Works
1. Data Model
- The
Contactclass encapsulates contact details and provides CSV serialization. toCSV()andfromCSV()enable file persistence.
2. Core Logic
ContactManagerhandles all CRUD operations and file I/O.- Contacts are stored in an
ArrayList<Contact>for dynamic management.
3. File Format
- Data is stored in
contacts.csvwith comma-separated values:
Alice,+1234567890,[email protected],123 Main St Bob,+0987654321,[email protected],456 Oak Ave
4. Validation
InputValidatoruses regex to ensure:- Phone numbers: 10–15 digits, optional
+prefix - Emails: Standard email format
5. User Interaction
- Menu-driven interface with clear prompts.
- Input validation prevents invalid data entry.
- Graceful handling of empty lists and invalid indices.
Sample Output
=== Contact Management System === Loaded 1 contacts from contacts.csv Choose an option: 1. Add Contact 2. View All Contacts 3. Search Contact 4. Update Contact 5. Delete Contact 6. Exit Enter your choice: 2 1. Name: Alice Phone: +1234567890 Email: [email protected] Address: 123 Main St Choose an option: 1. Add Contact 2. View All Contacts 3. Search Contact 4. Update Contact 5. Delete Contact 6. Exit Enter your choice: 3 Enter name or phone to search: Alice Name: Alice Phone: +1234567890 Email: [email protected] Address: 123 Main St Choose an option: 1. Add Contact 2. View All Contacts 3. Search Contact 4. Update Contact 5. Delete Contact 6. Exit Enter your choice: 6 Contacts saved to contacts.csv Goodbye!
Key Concepts Demonstrated
| Concept | Implementation |
|---|---|
| Object-Oriented Design | Contact class with encapsulation |
| Collections | ArrayList<Contact> for dynamic storage |
| File I/O | CSV read/write with BufferedReader/PrintWriter |
| User Input | Scanner with validation |
| CRUD Operations | Add, view, search, update, delete |
| Error Handling | Try-catch for I/O, input validation |
| Regular Expressions | Phone/email validation |
| Menu System | Loop with switch-case |
Possible Enhancements
- Unique ID generation: Add auto-incrementing contact IDs
- Sorting: Sort contacts by name or other fields
- Categories/Groups: Tag contacts (e.g., family, work)
- GUI version: Use JavaFX or Swing
- Database storage: Replace CSV with SQLite or MySQL
- Import/Export: Support vCard (.vcf) format
- Duplicate detection: Prevent adding identical contacts
Best Practices Applied
- Single Responsibility: Each class has one clear purpose
- Input validation: Prevents invalid data entry
- Resource management:
Scannerand file streams properly closed - Meaningful names: Clear variable and method names
- Persistence: Data survives application restarts
- User feedback: Clear success/error messages
- Modular design: Separation of concerns (model, logic, UI)
Conclusion
This Contact Management System provides a comprehensive foundation for learning Java fundamentals while building a functional application. It demonstrates how to structure code using OOP principles, manage data with collections, persist state with file I/O, validate user input, and create an interactive user experience. The modular design makes it easy to extend with new features, and the error handling ensures robustness. Whether used as a learning exercise or a starting point for a more advanced address book application, this project reinforces core Java skills that are applicable to real-world development.