본문 바로가기
카테고리 없음

고급자바 D3

by 현닝이 2022. 7. 22.
package kr.or.ddit.basic;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

/*
문제) 이름, 주소, 전화번호 속성을 갖는 Phone클래스를 만들고, 이 Phone클래스를 이용하여 
	  전화번호 정보를 관리하는 프로그램을 완성하시오.
	  이 프로그램에는 전화번호를 등록, 수정, 삭제, 검색, 전체출력하는 기능이 있다.
	  
	  전체의 전화번호 정보는 Map을 이용하여 관리한다.
	  (key는 '이름'으로 하고 value는 'Phone클래스의 인스턴스'로 한다.)


실행예시)
===============================================
   전화번호 관리 프로그램(파일로 저장되지 않음)
===============================================

  메뉴를 선택하세요.
  1. 전화번호 등록
  2. 전화번호 수정
  3. 전화번호 삭제
  4. 전화번호 검색
  5. 전화번호 전체 출력
  0. 프로그램 종료
  번호입력 >> 1  <-- 직접 입력
  
  새롭게 등록할 전화번호 정보를 입력하세요.
  이름 >> 홍길동  <-- 직접 입력
  전화번호 >> 010-1234-5678  <-- 직접 입력
  주소 >> 대전시 중구 대흥동 111  <-- 직접 입력
  
  메뉴를 선택하세요.
  1. 전화번호 등록
  2. 전화번호 수정
  3. 전화번호 삭제
  4. 전화번호 검색
  5. 전화번호 전체 출력
  0. 프로그램 종료
  번호입력 >> 5  <-- 직접 입력
  
  =======================================
  번호   이름       전화번호         주소
  =======================================
   1    홍길동   010-1234-5678    대전시
   ~~~~~
   
  =======================================
  출력완료...
  
  메뉴를 선택하세요.
  1. 전화번호 등록
  2. 전화번호 수정
  3. 전화번호 삭제
  4. 전화번호 검색
  5. 전화번호 전체 출력
  0. 프로그램 종료
  번호입력 >> 0  <-- 직접 입력
  
  프로그램을 종료합니다...
  
*/
public class T09PhoneBookTest {
	private Scanner scan;
	private Map<String, Phone> phoneBookMap; 
	
	public T09PhoneBookTest() {
		scan = new Scanner(System.in);
		phoneBookMap = new HashMap<String, Phone>();
	}
	
	// 메뉴를 출력하는 메서드
	public void displayMenu(){
		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(" 0. 프로그램 종료");
		System.out.print(" 번호입력 >> ");		
	}
	
	// 프로그램을 시작하는 메서드
	public void phoneBookStart(){
		System.out.println("===============================================");
		System.out.println("   전화번호 관리 프로그램(파일로 저장되지 않음)");
		System.out.println("===============================================");
		
		while(true){
			
			displayMenu();  // 메뉴 출력
			
			int menuNum = scan.nextInt();   // 메뉴 번호 입력
			
			switch(menuNum){
				case 1 : insert();		// 등록
					break;
				case 2 : update();		// 수정
					break;
				case 3 : delete();		// 삭제
					break;
				case 4 : search();		// 검색
					break;
				case 5 : displayAll();	// 전체 출력
					break;
				case 0 :
					System.out.println("프로그램을 종료합니다...");
					return;
				default :
					System.out.println("잘못 입력했습니다. 다시입력하세요.");
			} // switch문
		} // while문
	
	}
	
	/*
	 * 전화번호 정보를 수정하는 메서드
	 */
	private void update() {
		
		System.out.println();
		System.out.println("수정할 전화번호 정보를 입력하세요.");
		System.out.print("이름 >> ");
		String name = scan.next();
		
		//이미 등록된 사람인지 체크
		//get()메서드로 값을 가져올 때 가져올 자료가 없으면 null을 반환한다.
		if (phoneBookMap.get(name) == null) {
			System.out.println(name + "씨는 없는 사람입니다.");
			return;
		}
		System.out.print("전하번호>> ");
		String tel = scan.next();
		
		System.out.print("주소 >>");
		scan.nextLine(); //입력버퍼에 남아있는 엔터키값을 읽어와 버리는 역할 수행
						 //next()수행후 nextline()호출시 남아있을지 모를 엔터키
		                 //제거하기 위해 호출함.
		String addr = scan.nextLine();
		
		phoneBookMap.put(name, new Phone(name, tel, addr));
		System.out.println(name+"씨 수정완료 되었습니다.");
		}	
		
	

	/*
	 * 이름을 이용한 전화번호 정보 검색 메소드
	 */
	private void search() {
		System.out.println();
		System.out.println("검색할 전화번호 정보를 입력하세요.");
		System.out.println(("이름 >>"));
		String name= scan.next();
		Phone p = phoneBookMap.get(name);
		
		if(p == null) {
			System.out.println(name+ "씨의 전화번호 정보가 없습니다.");
		}else {
			System.out.println(name + "씨의 전화번호 정보");
			System.out.println("이     름:"+p.getName());
			System.out.println("전화번호:"+p.getTel());
			System.out.println("주      소:"+p.getAddr());
		}
		System.out.println("검색 작업 완료...");
	}

	/*
	 * 전화번호 정보를 삭제하기 위한 메서드
	 */
	private void delete() {
		System.out.println();
		System.out.println("삭제할 전화번호 정보를 입력하세요.");
		System.out.print("이름>> ");
		String name = scan.next();
		
		//remove(key) => 삭제를 성공하면 삭제된  value값을 반환하고,
		               //실패하면 null를 리턴한다.
		if(phoneBookMap.remove(name) == null){
			System.out.println(name+"씨는 등록된 사람이 아닙니다.");
	}else {
		System.out.println(name+"씨 정보를 삭제 하였습니다.");
	}

	/*
	 * 전화번호 정보를 수정하는 메서드
	 */

		
	}

/*
 * 전체 자료를 출력하는 메서드
 */
private void displayAll() {
	Set<String> keySet = phoneBookMap.keySet();
	System.out.println("=======================================");
	System.out.println("번호\t이름\t전화번호\t주소");
	System.out.println("=======================================");
	
	if(keySet.size()==0) {
		System.out.println("등록된 전화번호 정보가 없습니다.");
	}else {
		Iterator<String> it = keySet.iterator();
		int cnt = 0;
		while(it.hasNext()) {
			cnt++;
			String name = it.next(); //키값 가져오기
			Phone p = phoneBookMap.get(name); //get으로 값 가져오기  
			System.out.println(""+cnt+"\t"+p.getName()+"\t"+p.getTel()+"\t"+p.getAddr());
		}
	}
	System.out.println("=======================================");
	System.out.println("출력 완료...");
}

/*
 * 새로운 전화번호 정보를 등록하는 메서드
 * 이미 등록된 사람은 등록되지 않는다.
 */
private void insert() {
	System.out.println();
	System.out.println("새로게 등록할 전화번호 정보를 입력하세요.");
	System.out.print("이름 >> ");
	String name = scan.next();
	
	//이미 등록된 사람인지 체크
	//get()메서드로 값을 가져올 때 가져올 자료가 없으면 null을 반환한다.
	if (phoneBookMap.get(name) != null) {
		System.out.println(name + "씨는 이미 등록된 사람입니다.");
		return;
	}
	System.out.print("전하번호>> ");
	String tel = scan.next();
	
	System.out.print("주소 >>");
	scan.nextLine(); //입력버퍼에 남아있는 엔터키값을 읽어와 버리는 역할 수행
					 //next()수행후 nextline()호출시 남아있을지 모를 엔터키
	                 //제거하기 위해 호출함.
	String addr = scan.nextLine();
	
	phoneBookMap.put(name, new Phone(name, tel, addr));
	System.out.println(name+"씨 등록완료 되었습니다.");
	}

public static void main(String[]args) {
	new T09PhoneBookTest().phoneBookStart();
}
}
/*
 * 전화번호 정보를 저장할 수 있는 VO(value object값을 담기위한 객채)클래스 
 */
class Phone { 
	private String name; //이름
	private String tel;  //전화번호
	private String addr; //주소
	
	public Phone(String name, String tel, String addr) {
		super();
		this.name = name;
		this.tel = tel;
		this.addr = addr;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public String getAddr() {
		return addr;
	}

	public void setAddr(String addr) {
		this.addr = addr;
	}

	@Override
	public String toString() {
		return "Phone [name=" + name + ", tel=" + tel + ", addr=" + addr + "]";
	}
	
	
}​
package kr.or.ddit.basic;

import java.util.HashSet;
import java.util.Set;

public class T07EqualsHashcodeTest {
   /*
    해시함수(hash function)는 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수이다.
    해시함수에 의해 얻어지는 값은 해시값, 해시코드, 해시체크섬 또는 간단하게 해시라고 한다.
    
    HashSet, HashMap, Hashtable과 같은 객체들을 사용할 경우,
    객체가 서로 같은지를 비교하기 위해 equals()메서드와 hashCode()메서드를 호출한다.
    그래서 객체가 서로 같은지여부를 결정하려면 두 메서드를 재정의 해야한다.
    객체가 같은지 여부는 데이터를 추가할 때 검사한다.
    
    - equals()메서드와 hashCode()메서드에 관련된 규칠
    1. 두 객체가 같으면 반드시 같은 hashCode를 가져야 한다.
    2. 두 객체가 같으면 equals()호출했을때 true를 반환해야 한다.
         즉, 객체 a, b가 같으면 a.equals(b)와 b.equals(a) 둘다 true이어야 한다.
    3. 두 객체의 hashCode가 같다고 해서 두 객체가 반드시 같은 객체는 아니다.
            하지만 두 객체가 같으면 반드시 hashCode가 같아야 한다.
    4. equals()메서드를 override하면 반드시 hashCode()도 override해야 한다.
    5. hashCode()는 기본적으로 Heap메모리에 있는 각 객체에 대한 메모리 주소 매핑정보를 
            기반으로 한 정수값을 반환한다.그러므로,
            클래스에서 hashCode()메서드를 override하지 않으면 절대로 두 객체가 같은 것으로 간주될 수없다.
 */
   public static void main(String[] args) {

      String str = "홍길동";
      System.out.println(str.hashCode());
      // str.hashCode()값은 int값인 정수가 나옴 hashCode는 int타입이다.
      System.out.println(str.contentEquals(str));

      Person p1 = new Person(1, "홍길동");
      Person p2 = new Person(1, "홍길동");
      Person p3 = new Person(1, "이순신");

      // 오브젝트 관점에서는 false 생성됨 p1과 p2는 생성되는 메모리 위치가 달라서
      System.out.println("p1.equals(p2) : " + p1.equals(p2));
      System.out.println("p1 == p2 : " + (p1 == p2));
      // 오브젝트에서 같은 값으로 보려면 p1 == p1으로 해야함
      System.out.println("p1 == p1 : " + (p1 == p1));

      System.out.println(p1.hashCode());
      System.out.println(p2.hashCode());

      // 이경우 2112로 다른값을 넣었는데 해쉬코드는 같은 값이 나오는 충돌이 발생함
      System.out.println("Aa".hashCode());
      System.out.println("Bb".hashCode());

      Set<Person> set = new HashSet<Person>();

      set.add(p1);
      set.add(p2);
      System.out.println("p1, p2등록 후 데이터 : ");

      for (Person p : set) {
         System.out.println(p.getId() + " : " + p.getName());
      }

      System.out.println("add(p3) 성공여부 : " + set.add(p3));
      System.out.println("add(p3) 후 데이터 : ");
      for (Person p : set) {
         System.out.println(p.getId() + " : " + p.getName());
      }
      System.out.println("remove(p2) 성공여부 : " + set.remove(p2));
      System.out.println("remove(p2) 후 데이터 : ");

      for (Person p : set) {
         System.out.println(p.getId() + " : " + p.getName());
      }
   }
}

//extends Object 이건 자동생성이라 생략되어있음
class Person {
   private int id;
   private String name;

   public Person(int id, String name) {
      super();
      this.id = id;
      this.name = name;
   }

   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   @Override
   public String toString() {
      return "Person [id=" + id + ", name=" + name + "]";
   }

//   @Override
//   public int hashCode() {
//      return (name + id).hashCode();
//   }
//   @Override
//   public boolean equals(Object obj) {
//      Person = p (Person) obj;
//      return this.getId() == p.getId() && this.getName().equals(p.getName());
//   }
   @Override
   public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + id;
      result = prime * result + ((name == null) ? 0 : name.hashCode());
      return result;
   }

   @Override
   public boolean equals(Object obj) {
      if (this == obj)
         return true;
      if (obj == null)
         return false;
      if (getClass() != obj.getClass())
         return false;
      Person other = (Person) obj;
      if (id != other.id)
         return false;
      if (name == null) {
         if (other.name != null)
            return false;
      } else if (!name.equals(other.name))
         return false;
      return true;
   }

}

 

<Map 인터페이스 특징>

1)key 값과 value값을 한쌍 (Entry) 의 데이터로 관리한다.

2)key 값은 중복을 허용하지 않고, 순서를 유지 하지 않는다(Set의 특징)

3)value값은 중복을 허용한다(List의 특징)

package kr.or.ddit.basic;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class T08MapTest {
public static void main(String[] args) {
	
	//key와 value가 허용할 타입을 정의
	Map<String, String> map = new HashMap<String, String>();
	
	// 자료 추가 => put(key값, value 값) //key와 value의 쌍을 entry 라고한다
	map.put("name", "홍길동");
	map.put("addr", "대전");
	map.put("tel", "010-1234-5678");

	System.out.println("map =>" + map);
	
	//자료 수정 => 데이터를 저장할 때 key값이 같으면 나중에 입력한 값이 저장된다.
	//         put(수정할 key값, 새로운 value값)
	map.put("addr", "서울");
	System.out.println("map => " + map);

	//자료 삭제 => remove(삭제할 key 값)
	map.remove("name");
	System.out.println("map => " + map);
	
	//자료 읽기 => get(key 값)
	System.out.println("addr = " + map.get("addr"));
	System.out.println("======================================");
	
	//key 값들을 읽어와 자료를 출력하는 방법
	
	//방법 1 => keySet()메서드 이용하기 
	//        keySet() : Map의 key 값들만 읽어와 Set형으로 반환한다.
	Set<String>keySet = map.keySet();
	
	System.out.println("Iterator를 이용한 방법");
	Iterator<String>it = keySet.iterator();
	while(it.hasNext()) {
		String key = it.next();
		System.out.println(key+":"+map.get(key));
	}
	System.out.println("------------------------------------------");
	
	//방법2 => Set 형의 데이터를 '향상된 for문' 으로 처리하는 방법
	System.out.println("향상된 for문을 이용한 방법");
	for(String key : keySet) {
		System.out.println(key+":"+map.get(key));
	}
	System.out.println("--------------------------------------------");
	
	//방법3 => value값만 읽어와  출력하기 => values() 이용하기
	System.out.println("values()를 이용한 방법");
	for(String value : map.values()) {
		System.out.println(value);
	}
	System.out.println("--------------------------------------------");
	
	//방법4 => Map 관련 클래스에는 Map.Entry타입의 내부 클래스가 만들어져 있다.
	//        이 내부 클래스는 key와 value라는 멤버변수로 구성되어있다.
	//        Map에서 이Map.Entry타입의 객체들을 Set형으로 저장하여 관리한다.
	
	//Map.Entry 타입의 객체 모두 가져오기 => entrySet() 이용하기
	 Set<Map.Entry<String, String>> entrySet = map.entrySet();
	
	 //가져온 Entry 객체들을 순서대로 처리하기 위해서 Iterator 객체 이용
	 Iterator<Map.Entry<String, String>> entryIt = entrySet.iterator();
	 
	while(entryIt.hasNext()) {
		Map.Entry<String, String> entry = entryIt.next();
	
			 
	 System.out.println("key값: " + entry.getKey());
	 System.out.println("value값: " + entry.getValue());
	 System.out.println();
}
}
}
package kr.or.ddit.basic;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class T10PropertiesTest {
	/*
	 *  Properties 는 Map보다 축소된 기능의 객체라고 할 수 있다.
	 *  Map은 모든 형태의 객체 데이터를 key와 value값으로 사용할 수 있지만
	 *  Properties는 key와 value값으로 String만 사용할 수 있다.
	 *  
	 *  Map은 put(), get() 메서드를 이용하여 데이터를 입출력하지만
	 *  Properties 는 setProperty(),getProperty() 메서드를 통해서
	 *  데이터를 입출력한다.	
	 */
	public static void main(String[] args) throws  IOException {
		Properties prop = new Properties();
		
		prop.setProperty("name", "홍길동");
		prop.setProperty("tel", "010-1234-5678");
		prop.setProperty("addr", "대전");
		
		String name = prop.getProperty("name");
		String tel = prop.getProperty("tel");
		
		System.out.println("이름: "+name);
		System.out.println("전화: "+tel);
		System.out.println("주소: "+prop.getProperty("addr"));
		
		//내용을 파일로 저장하기
		prop.store(new FileOutputStream("src/kr/or/ddit/basic/test.properties"), "코멘트입니다.");
	}
}