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.