이번에는 HashSet을 이용해서 중복값은 저장이 안 되는 전화번호부를 구현했다.
중복되는 이름이나 전화번호를 입력하려고 할 때, 오류 메세지가 뜨고 입력 자체를 거부하는 방법을 구현해보고 싶었지만 이번에는 그 단계까지 해보지는 못 하였고, 단순히 이미 입력된 값을 또 입력하려고 하면 입력한 값이 저장되지 않게만 구현해 보았다.
public class PhoneInfo {
private String name;
private String phoneNum;
PhoneInfo (String name, String phoneNum) {
this.name = name;
this.phoneNum = phoneNum;
}
public void showPhoneInfo() {
System.out.println("이름 : " + name);
System.out.println("전화번호 : " + phoneNum);
}
public String getName() {
return name;
}
public String getPhoneNum() {
return phoneNum;
}
//hashSet 에서 객체의 동등을 비교할 때는 hashCode와 equals 메소드를 모두 사용함
@Override
public int hashCode() {
// 값이 저장된 개념적 주소를 리턴
return name.hashCode();
//동일한 문자열 이름이라면, 자바에서 새로운 공간을 할당하지 않고 기존 문자열을 가리키도록 만듦
}
@Override
public boolean equals(Object obj) {
// 전달받은 객체가 PhoneInfo 타입이 맞는지 확인
if ( obj instanceof PhoneInfo ) {
PhoneInfo pi = (PhoneInfo) obj;
//맞다면 자식의 자료형으로 명시적 형변환 처리
if ( pi.getName().equals(name) ) {
return true;
}
}
return false;
}
}
PhoneInfo는 저번 주소록과 달라진 점은 없고, 밑에 hashCode와 equals 메소드가 추가됐다.
HashSet에서는 객체의 동등을 비교하고자 할 때 hashCode로 저장된 값의 개념적 주소를 먼저 리턴하고, equals 로 내용값이 일치하는지 이중으로 확인을 거친다.
HashSet 메소드에서 super.hashCode가 아닌 name.hashCode를 리턴할 수 있도록 오버라이딩 했으며,
equals 메소드는 pi 에서 받은 이름과 입력한 이름이 일치하는지 여부를 확인할 수 있도록 오버라이딩했다.
public class PhoneUnivInfo extends PhoneInfo {
private String major;
private int grade;
PhoneUnivInfo (String name, String phoneNum, String major, int grade) {
super(name, phoneNum);
this.major = major;
this.grade = grade;
}
@Override
public void showPhoneInfo() { // 오버라이딩: 재정의
super.showPhoneInfo();
System.out.println("전공 : "+major);
System.out.println("학년 : "+grade);
}
}
public class PhoneCompanyInfo extends PhoneInfo {
private String company;
PhoneCompanyInfo(String name, String phoneNum, String company) {
super(name, phoneNum);
this.company = company;
}
@Override
public void showPhoneInfo() { // 오버라이딩: 재정의
super.showPhoneInfo();
System.out.println("회사 : "+company);
}
}
PhoneInfo의 자식 클래스이기 때문에 부모 클래스에서 추가한 메소드가 상속되므로 showPhoneInfo() 메소드만 오버라이드했다.
import java.util.HashSet;
import java.util.Iterator;
public class PhoneBookManager {
HashSet<PhoneInfo> list = new HashSet<PhoneInfo>();
// 추가적인 생성자 오버로딩이 없다면 기본 생성자는 생략가능함
private PhoneBookManager() {
}
static PhoneBookManager inst = null;
public static PhoneBookManager createManagerInst() {
if (inst == null) // 객체를 만든 적이 없다면
inst = new PhoneBookManager(); // 생성해서 초기화해주고
return inst; // 객체 한 개만 만들어서 공유함
}// 싱글톤.
public void readData() {
System.out.println("데이터 입력을 시작합니다.");
System.out.println("1.일반, 2.대학, 3.회사");
int kinds = PhoneBook.sc.nextInt();
PhoneBook.sc.nextLine();
System.out.print("이름 : ");
String name = PhoneBook.sc.nextLine();
System.out.print("전화번호 : ");
String phoneNum = PhoneBook.sc.nextLine();
PhoneInfo pi = null; // 연락처를 입력받을 pi객체 생성 및 초기화
switch (kinds) { // 각 메소드에서 리턴된 값을 pi에 넣어줌
case 1:
pi = new PhoneInfo(name, phoneNum);
break;
case 2:
System.out.print("전공 : ");
String major = PhoneBook.sc.nextLine();
System.out.print("학년 : ");
int grade = PhoneBook.sc.nextInt();
pi = new PhoneUnivInfo(name, phoneNum, major, grade);
break;
case 3:
System.out.print("회사 : ");
String company = PhoneBook.sc.nextLine();
pi = new PhoneCompanyInfo(name, phoneNum, company);
break;
}
list.add(pi);// 값이 들어간 pi를 list 안에 넣는 작업
System.out.println("데이터 입력이 완료되었습니다.");
}
public void searchData() {
System.out.print("데이터 검색을 시작합니다.\n 검색할 이름 : ");
String name = PhoneBook.sc.nextLine();
Iterator<PhoneInfo> itr = list.iterator();
while (itr.hasNext()) {
PhoneInfo pi = itr.next();
if (name.equals(pi.getName())) {
pi.showPhoneInfo();
System.out.println("데이터 검색이 완료되었습니다.");
}
}
}
public void deleteData() {
System.out.println("데이터 삭제를 시작합니다.\n삭제할 이름 : ");
String name = PhoneBook.sc.nextLine();
Iterator<PhoneInfo> itr = list.iterator();
while (itr.hasNext()) {
PhoneInfo pi = itr.next();
if (name.equals(pi.getName())) {
list.remove(pi);
System.out.println("데이터가 삭제되었습니다.");
}
}
}
public void printAllData() {
System.out.println("전체 데이터를 출력합니다.");
System.out.println("현재 저장된 데이터의 개수는 " + list.size() + "개 입니다.");
Iterator<PhoneInfo> itr = list.iterator();
while (itr.hasNext()) {
PhoneInfo pi = itr.next();
pi.showPhoneInfo();
}
System.out.println("--------------------------");
}
}
기존에는 phoneList[i] 라는 객체 배열을 생성해서 이 배열 안에 주소록을 저장했지만,
hashSet은 순서와 상관 없이 중복값을 담을 수 없으므로 객체 배열 대신 hashSet을 사용했다.
전체적으로 처리 메소드에서 for 문 대신 Iterator와 while 문을 활용했다.
list에서는 index 값이 있지만, Set은 순서가 없는 컬렉션이기 때문에 index가 없다.
Iterator의 hashNext를 이용하면 true를 출력할 수 있으므로 while 문을 무한반복하게 하고 더 이상 입력값이 없을 경우에 while문을 빠져나오게 하는 것이 가능하다.
Iterator의 장점
1. 컬렉션에서 요소를 제어하는 기능
2. next() 및 previous()를 써서 앞뒤로 이동하는 기능
3. hasNext()를 써서 더 많은 요소가 있는지 확인하는 기능
이전에 사용했던 nameIndex 메소드를 더 이상 사용하지 않는다.
입력된 이름 값이 배열의 몇 번 째에 위치하고 있는지가 hashSet 에서는 의미가 없기 때문이다.
기존과 달리 이번에는 이름값을 equals 메소드를 이용하여 찾으면 된다.
그리고 검색과 삭제 기능도 훨씬 간결하게 구현이 가능해졌다.
전체출력은 검색과 비슷하지만 while문으로 반복 작용하게 만들어서 모든 내용을 다 출력하게 하기만 하면 된다.
import java.util.Scanner;
public class PhoneBook {
static Scanner sc = new Scanner(System.in);
//스태틱으로 만들어서 다른 클래스와 Scanner 공유
public static void main(String[] args) {
PhoneBookManager.createManagerInst();
int ch;
while (true) {
showMenu();
ch = sc.nextInt();
sc.nextLine(); //이후 nextLine 쓸 때 오류 방지를 하기 위해 미리 한 칸 띄워줌
switch (ch) {
case 1:
PhoneBookManager.inst.readData();
break;
case 2:
PhoneBookManager.inst.searchData();
break;
case 3:
PhoneBookManager.inst.deleteData();
break;
case 4:
PhoneBookManager.inst.printAllData();
break;
case 5:
System.out.println("프로그램을 종료합니다.");
sc.close();
System.exit(0);
}
}
}
static void showMenu() {
System.out.println("메뉴를 선택하세요.");
System.out.println("----------------");
System.out.println("1.데이터 입력");
System.out.println("2.데이터 검색");
System.out.println("3.데이터 삭제");
System.out.println("4.데이터 전체출력");
System.out.println("5.프로그램 종료");
System.out.println("----------------");
}
}
기존에는 PhoneBookManager manager = new PhoneBookManager; 라고 생성자를 호출해서 메소드를 이용했지만, PhoneBookManager 클래스에서 createManagerInst 메소드를 static으로 만들었기 때문에 바로 호출해서 사용했다.
'개발입문 > JAVA 세미프로젝트' 카테고리의 다른 글
[JAVA] 콘솔용 POS 프로그램 만들기 (0) | 2022.10.12 |
---|---|
[JAVA] Stream을 이용하여 파일 저장이 가능한 전화번호부 만들기 (0) | 2022.10.12 |
[JAVA] 상속과 오버라이딩을 이용하여 카테고리가 있는 전화번호부 만들기 (0) | 2022.10.12 |
[JAVA] 배열을 이용한 전화번호부 만들기 (0) | 2022.10.12 |
댓글