16일차 2023-03-29

2023. 3. 29. 20:41java

1. Collection의 AddressBook.java

 

private을 붙인 멤버 변수를 생성

한 명의 이름/나이 주소/생일 저장하는 address클래스 생성

Comparable 인터페이스 구현- 인자 한 개짜리 Collections.sort(List컬랙션)  사용

Collections.sort(리스트 한 개짜리)를 적용하려면 그 리스트 컬렉션에 저장된 객체는 반드시 Comparable 해야 된다.

compareTo(Address target) 메소드를 오버라이딩할 때 

오른 차순은 return부분에서 멤버변수name - 매개변수.name 이런식으로 앞에서 뒤에껄 빼면 디폴트인 오른차순

뒤의 target.name(매개변수)에서 앞(멤버변수 name)을 빼면 내림차순 

두 가지 방법으로  구현

AddressBook.java

package collection20;

import java.sql.Date;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

//한 명의 이름/나이/주소/생일을 저장하는 클래스]
//방법1. Comparable인터페이스 구현- Collections.sort(List컬렉션) 인자 하나짜리 사용
//      Collections.sort(리스트컬렉션)를 적용하려면 리스트 컬렉션에 저장된 객체(타입)은 반드시 Comparable을 구현해야한다
class Address /* implements Comparable<Address>//방법1을 할때 주석풀기*//{
	//[멤버변수]
	private String name;
	private int age;
	private String addr;
	private Date birthday;
	
	//정렬시 사용할 상수
	public static final int SORT_BY_NAME=1;//디폴트
	public static final int SORT_BY_AGE=2;
	public static final int SORT_BY_ADDRESS=3;
	public static final int SORT_BY_BIRTHDAY=4;
	
	//방법1일때-정렬시 구분자로 사용할 정적 필드(디폴트는 이름으로 정렬)
	//public static int sortField =SORT_BY_NAME;
	
	//[인자 생성자]
	public Address(String name, int age, String addr, Date birthday) {		
		this.name = name;
		this.age = age;
		this.addr = addr;
		this.birthday = birthday;
	}//////////////////
	@Override
	public String toString() {
		return String.format("[이름:%s,나이:%s,주소:%s,생일:%s]",name,age,addr,birthday);
	}///////////////////////
	/*
	//방법1일때
	@Override
	public int compareTo(Address target) {
		switch(sortField) {
			case SORT_BY_NAME:
				return name.compareTo(target.name);//오름차순
			case SORT_BY_AGE:
				return age - target.age;
			case SORT_BY_ADDRESS:
				return addr.compareTo(target.addr);
			default:return birthday.toString().compareTo(target.birthday.toString());
		}		
	}*/
	//방법2 일때 게터 추가
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
	public String getAddr() {
		return addr;
	}
	public Date getBirthday() {
		return birthday;
	}
}///////////////////
public class AddressBookApp {
	
	/*
	방법2. 정렬용 메소드 정의해서 사용.
	1.리스트컬렉션에 저장할 객체인 Address가 Comparable인터페이스를 구현할 필요가 없다.
	2.정렬시 구분자로 사용할 정적 필드(sortField)도 필요없다
	정렬시 Collections.sort(List컬렉션,Comparator타입) 인자 두개 짜리 사용
	*/
	public static void sort(int sortField,List<Address> values) {
		Collections.sort(values, new Comparator<Address>() {

			@Override
			public int compare(Address src, Address target) {
				switch(sortField) {
					case Address.SORT_BY_NAME:
						return src.getName().compareTo(target.getName());//오름차순
					case Address.SORT_BY_AGE:
						return src.getAge() - target.getAge();
					case Address.SORT_BY_ADDRESS:
						return src.getAddr().compareTo(target.getAddr());
					default:return src.getBirthday().toString().compareTo(target.getBirthday().toString());
				}		
			}
			
		});
	}///////////////////

	public static void main(String[] args) {
		/*
		1]자음을 Key값-String 혹은 Character		  
		  List계열 컬렉션을 Value값-List<String>
		  Map계열 컬렉션-Value에는 자음에 해당하는 이름들 저장
		*/
		Map<Character, List<String>> nameAddresses = new HashMap<>();
		//1-1]이름 저장용 List계열 컬렉션 객체 생성 및 이름 저장]
		List<String> kieyeok = Arrays.asList("고길동","곽길동","가길동","강길동");
		List<String> nieoun = Arrays.asList("노길동","나길동","남길동");
		//1-2]Map컬렉션(nameAddresses)에 이름이 저장된 List계열 컬렉션 저장
		nameAddresses.put('ㄱ', kieyeok);
		nameAddresses.put('ㄴ', nieoun);
		System.out.println("[키값을 알때]");
		List<String> values=nameAddresses.get('ㄱ');
		for(String value:values) System.out.println(value);
		System.out.println("[키값을 모를때]");
		//1]keySet()으로 Set컬렉션 얻기
		Set<Character> keys= nameAddresses.keySet();
		//2]Set컬렉션에 확장 for문 적용
		for(Character key:keys) {
			System.out.println(String.format("[%c로 시작하는 명단]",key));
			//3]get(키값)으로 value얻기
			values=nameAddresses.get(key);
			for(String value:values) System.out.println(value);
		}////////
		/*
		2] 초성을 Key값-String 혹은 Character		 
		   List계열 컬렉션을 Value값-List<Map<String,Object>>
		   Map계열 컬렉션-Value에는 초성에 해당하는 이름,주소,전화번호,나이들 저장
		*/
		Map<Character,List<Map<String,Object>>> address = new HashMap<>();
		//2-1]이름/전번/주소/나이가 저장된 맵 컬렉션을 저장할 리스트계열 컬렉션 객체 생성.
		List<Map<String,Object>> kie = new Vector<>();
		List<Map<String,Object>> nie = new Vector<>();
		
		Map<String,Object> k= new HashMap<>();
		k.put("name", "고길동");
		k.put("age",20);
		k.put("addr", "가산동");
		k.put("birthday", new Date(new java.util.Date().getTime()));
		kie.add(k);
		k= new HashMap<>();
		k.put("name", "곽길동");
		k.put("age",30);
		k.put("addr", "서초동");
		k.put("birthday", new Date(new java.util.Date().getTime()));
		kie.add(k);
		
		Map<String,Object> n= new HashMap<>();
		n.put("name", "나길동");
		n.put("age",25);
		n.put("addr", "나산동");
		n.put("birthday", new Date(new java.util.Date().getTime()));
		nie.add(n);
		
		n= new HashMap<>();
		n.put("name", "노길동");
		n.put("age",35);
		n.put("addr", "방배동");
		n.put("birthday", new Date(new java.util.Date().getTime()));
		nie.add(n);
		
		//주소록 저장하는 맵컬렉션에 리스트 저장]
		address.put('ㄱ', kie);
		address.put('ㄴ', nie);
		/*
		  객체 꺼내올때]
		  Set/List계열(Collection계열) 무조건 확장 for문 사용
		  Map계열은 keySet()으로 키값들이 저장된
		  Set계열 반환 받은 후 확장 for문 사용	
		 */
		System.out.println("[키값을 알때]");
		List<Map<String,Object>> lists=address.get('ㄴ');
		for(Map<String,Object> map:lists) {
			Set<String> sets= map.keySet();
			for(String key:sets) {
				Object value = map.get(key);
				System.out.println(String.format("%s:%s",key,value));
			}
		}
		System.out.println("[키값을 모를때]");
		keys=address.keySet();
		for(Character key:keys) {
			System.out.println(String.format("[%c로 시작하는 명단]",key));
			lists=address.get(key);
			for(Map<String,Object> map:lists) {
				Set<String> sets= map.keySet();
				for(String ky:sets) {
					Object value = map.get(ky);
					System.out.println(String.format("%s:%s",ky,value));
				}
			}
		}/////////////////
		
		//3]Address클래스를 사용해서 2]번 처럼 구현
		Map<Character,List<Address>> addressBook = new HashMap<>();
		//3-1]주소를 저장할 리스트 계열 컬렉션 생성
		List<Address> kiec = new Vector<>();
		List<Address> niec = new Vector<>();
		//3-2]주소 저장
		long epochTime =new java.util.Date().getTime();
		kiec.add(new Address("곽길동", 40, "가산동", new Date(epochTime)));
		kiec.add(new Address("고길동", 20, "청담동", new Date(epochTime)));
		kiec.add(new Address("가길동", 35, "사당동", new Date(epochTime)));
		
		niec.add(new Address("노길동", 45, "가산동1", new Date(epochTime)));
		niec.add(new Address("나길동", 25, "청담동1", new Date(epochTime)));
		niec.add(new Address("남길동", 35, "사당동1", new Date(epochTime)));
		//3-3]키값으로 리스트 컬렉션 객체를 맵(addressBook)에 저장
		addressBook.put('ㄱ', kiec);
		addressBook.put('ㄴ', niec);
		System.out.println("[한 사람의 정보를 저장하는 클래스를 사용해서 구현]");
		keys=addressBook.keySet();
		for(Character key:keys) {
			System.out.println(String.format("[%c로 시작하는 명단]",key));
			List<Address> vals=addressBook.get(key);
			//출력전 정렬
			//[방법1으로 정렬시]
			//디폴트인 이름으로 정렬시
			//Collections.sort(vals);
			//나이로 정렬시
			//Address.sortField=Address.SORT_BY_AGE;
			//Collections.sort(vals);
			//[방법2으로 정렬시]
			sort(Address.SORT_BY_ADDRESS,vals);
			for(Address val:vals) {
				System.out.println(val);
			}
		}
	}////////////main
}//////////////class

sol)

추가)

 

2. 만들었던 메뉴 프로그램에서 자음, 오름차순, 내림차순으로 학생, 선생을 출력하기 위한 샘플 코드

AddressProjectSample.java

package collection20;

import java.sql.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.Vector;

import common.utility.CommonUtil;

public class AddressProjectSample {

	public static void main(String[] args) {
		Map<Character,List<Address>> addressBook = new HashMap<>();
		Scanner sc = new Scanner(System.in);
		//1]밸류 타입을 null로 초기화
		List<Address> valueList=null;
		while(true) {
			
			System.out.println("이름을 입력하세요?(종료시 EXIT)");
			String name = sc.nextLine().trim();
			if(name.equalsIgnoreCase("EXIT")) break;
			//2]입력한 이름에서 자음 (ㄱ,ㄴ,ㄷ,.....ㅎ)얻기
			char jaeum= CommonUtil.getJaeum(name);
			//System.out.println(jaeum);
			if(jaeum=='0') {
				System.out.println("한글명이 아닙니다");
				continue;
			}
			System.out.println("주소를 입력하세요?");
			String addr = sc.nextLine().trim();
			System.out.println("나이를 입력하세요?");
			int age = Integer.parseInt(sc.nextLine().trim());
			Date birthday = new Date(new java.util.Date().getTime());
			//맵컬렉션(addressBook)에 jaeum 키값이 존재하는지 판단
			if(!addressBook.containsKey(jaeum)) {//키값이 없는 경우.즉 맵컬렉션에 해당 키값이 저장이 안되어 있는 경우
				valueList = new Vector<>();//value타입인 List<Address>객체 생성
			}
			else {//키값이 존재한다면
				valueList=addressBook.get(jaeum);
			}
			//입력한 정보로 Address타입 생성후 맵의 value에 추가
			valueList.add(new Address(name, age, addr, birthday));
			//4]맵 컬렉션에 jaeum키값으로 저장
			addressBook.put(jaeum,valueList);		
			
		}/////////////while
		
		//출력]
		Set<Character> keys= addressBook.keySet();
		for(Character key:keys) {
			System.out.println(String.format("[%c로 시작하는 명단]",key));
			List<Address> values= addressBook.get(key);
			for(Address value:values) System.out.println(value);
		}/////////////////////////
		/*
    	문]찾고자 하는 사람의 이름을 입력받아
          위 맵 컬렉션(addressBook)에 저장된 사람의 정보를 출력하자.
          만약 해당하는 사람이 없으면 "해당하는 사람이 없어요"라고 출력하여라.
       	  찾을때까지 계속 입력받도록 하여라.
       */
		while(true) {
			System.out.println("찾는 사람의 이름을 입력하세요?");
			String name = sc.nextLine().trim();
			boolean isExist = false;
			for(Character key:keys) {
				List<Address> values= addressBook.get(key);
				for(Address value:values) {
					if(value.getName().equals(name)) {
						System.out.println(value);
						isExist=true;
						break;
					}
				}
				if(isExist) break;
			}
			if(isExist) break;
			else System.out.println("해당하는 사람이 없어요");			
		}
		
	}////////////////main
}///////////////////class

 

sol)

//2] 입력한 이름에서 자음 (ㄱ,ㄴ,ㄷ,.....ㅎ) 얻기

char jaeum= CommonUtil.getJaeum(name); 를 하기 위한

이름에서 자음을 구하여 반환하는 메소드 

common.utility 패키지에서 CommonUtil.java

package common.utility;

public class CommonUtil {
	
	//이름에서 자음을 구해 반환 하는 메소드]
	public static char getJaeum(String name) {
		//김길동->ㄱ,박길동->ㅂ, 홍길동->ㅎ
		//방법1]
		char[] jaeum=name.toCharArray();
		/*
		if(jaeum[0] >='가' && jaeum[0] < '나') return 'ㄱ';
		else if(jaeum[0] >='나' && jaeum[0] <'다') return 'ㄴ';
		else if(jaeum[0] >='다' && jaeum[0] <'라') return 'ㄷ';
		else if(jaeum[0] >='라' && jaeum[0] <'마') return 'ㄹ';
		else if(jaeum[0] >='마' && jaeum[0] <'바') return 'ㅁ';
		else if(jaeum[0] >='바' && jaeum[0] <'사') return 'ㅂ';
		else if(jaeum[0] >='사' && jaeum[0] <'아') return 'ㅅ';
		else if(jaeum[0] >='아' && jaeum[0] <'자') return 'ㅇ';
		else if(jaeum[0] >='자' && jaeum[0] <'차') return 'ㅈ';
		else if(jaeum[0] >='차' && jaeum[0] <'카') return 'ㅊ';
		else if(jaeum[0] >='카' && jaeum[0] <'타') return 'ㅋ';
		else if(jaeum[0] >='타' && jaeum[0] <'파') return 'ㅌ';
		else if(jaeum[0] >='파' && jaeum[0] <'하') return 'ㅍ';
		else if(jaeum[0] >='하' && jaeum[0] <='힣') return 'ㅎ';
		*/
		//방법2]
		char[] startChar= {'가','나','다','라','마','바','사','아','자','차','카','타','파','하'};
		char[] endChar= {'낗','닣','띻','맇','밓','삫','앃','잏','찧','칳','킿','팋','핗','힣'};
		char[] returnChar= {'ㄱ','ㄴ','ㄷ','ㄹ','ㅁ','ㅂ','ㅅ','ㅇ','ㅈ','ㅊ','ㅋ','ㅌ','ㅍ','ㅎ'};
		
		for(int i=0;i<startChar.length;i++) {
			if(jaeum[0] >=startChar[i] && jaeum[0]<=endChar[i])
				return returnChar[i];
		}
		return '0';//자음이 아닌 경우
	}
}

3. AcademyCollectionLogic.java에서 printPerson() 메소드에서 

학생과 교사를 출력하는데 가나다.... 오름차순으로, 내림차순으로 정렬하여 출력하기

(코드 3줄 추가)

private void printPerson() {
		
		//먼저 정렬하기
		//Collections.sort(person);//Comparable구현시
		//person.sort(Comparator.naturalOrder());//오름 차순
		person.sort(Comparator.reverseOrder());//내림 차순
		
		StringBuffer student = new StringBuffer("[학생 목록]\r\n");
		StringBuffer teacher = new StringBuffer("[교사 목록]\r\n");
		for(Person p:person)
				if(p instanceof Student)
					student.append(p.get()+"\r\n");
				else
					teacher.append(p.get()+"\r\n");
		
		System.out.println(student.toString()+teacher);
	}

4. 예외처리

컴파일 에러

-컴파일이 발생하는 에러는

 

1. 문법(syntax) 에러

2. IOException(예외 클래스)

3. SQLException(예외 클래스) 등등

 

4. Checked Exception(컴파일 에러)

컴파일러가 판단할 수 있는 에러. 실행 전에 체크가 가능한 에러

IOException( IO = nputOutput )

2번은 ex) System.read()가 있는데

이건 예전에 입력을 받을 때 썼었다. 입력을 사용자가 키보드로 받는데 이때 자바에서는 외부자원으로 판단.

이 키보드는 JVM에서 들어있는가 그렇지 않기 때문

자바는 외부 자원을 예외를 발생시키고 본다(빨간 줄)

해결방법)

호출한 메소드(예로 main) throws 예외클래스를 해주거나

try ~catch를 해주면 됨.

 

5. 런타임 에러(UnChecked Exception)

컴파일 시 체크가 안되는데 실행하면 콘솔에 에러 발생

ex) RuntimeException계열

NullPointerException => 예로 null값으로 무언가 참조할 때 

ArithmeticException => 나누기 0으로 했을 때

ArrayIndexOutOfBoundsException => 배열의 크기를 벗어난 인덱스 사용 시 (배열의 자리가 없는데 값을 넣으려 할 때)

 

main메서드에서는 throws해도 오류 발생 => 직접 처리 try~catch문 써야 된다 

예외 발생 시 JVM은 해당 예외클래스를 인스턴스화해서 예외 객체를 프로그램 쪽에 전달함

 

ExceptionBasic.java

package exception21;

import java.io.IOException;
import java.util.Date;
import java.util.InputMismatchException;
import java.util.Scanner;

public class ExceptionBasic {

	public static void main(String[] args) /*방법1 throws IOException */ {
		/*
		1]컴파일 에러(Checked Exception):
			- 컴파일시 발생하는 에러
			- Syntax에러(문법오류) ,IOException(예외 클래스),SQLException(예외클래스)등
			- 컴파일이 안되면 실행이 안됨.
			- 컴파일 에러(외부 자원 사용시 발생하는 컴파일에러:IOException,SQLException)는 
			  던지거나(throws) 
			  직접 처리(try~catch절) 할 수 있다
			  단,Syntax오류(문법오류)는 직접 수정해야 함			  	
		*/
		//1-1]Syntax에러
		//Int num;//[x]해결책 I를 i로
		int num;//[o]
		
		if(true); {}
		//else {}//[x]else는 항상 if 와 짝을 이루어야 한다.
		/* 
	  	※자바에서는 외부에 있는 자원을 사용하고자 할때는
	   	무조건 예외를 발생시킨다.(컴파일 에러의 한 종류)
	   	read()는 IOExcpetion을 던진다.
	   	read()메소드를 호출한 쪽에서는 
	   	예외를 다시 던지거나 try~catch절로 직접
	   	예외를 처리해야 한다. 	     

     	방법1]예외 던지기
     	호출한 메소드() throws 예외클래스{
    
     	}*/
		//방법1]예외를 또 던진다
		//System.in.read();
		//방법2]try~catch절로 직접 예외 처리
		/*
		try {
			System.in.read();
		} 
		catch (IOException e) {e.printStackTrace();}*/
		/*
		2]런타임 에러(UnChecked Exception)
		- 컴파일시에는 체크가 안됨.실행시에만 발생되는 에러
		-  RuntimeException계열(
		   NullPointerException,ArithmeticException,
		   ArrayIndexOutOfBoundsException등)
		- main메소드에서는 throws해도 오류발생.
		    즉 직접 처리(try~catch절)해야만 한다
		  
		  ※예외 발생시 JVM은 해당 예외클래스를 인스턴스화 해서
		   예외 객체를 프로그램쪽에 전달한다.
		*/
		//[ArrayIndexOutOfBoundsException]:
		// 배열의 크기를 벗어난 인덱스 사용시.
		try {
			int[] array = new int[2];
			array[0]=100;
			System.out.println("array[0]:"+array[0]);
			array[1]=200;
			System.out.println("array[1]:"+array[1]);
			array[2]=300;
			System.out.println("array[2]:"+array[2]);
		}
		catch(ArrayIndexOutOfBoundsException e) {
			System.out.println("예외가 발생했어요");
			System.out.println("관리자에게 문의하세요");
		}
		//[NumberFormatException]:숫자형식의 문자열을 
	    //int형으로 변환시 해당 문자열이 숫자형식이 아닐때.
		Scanner sc = new Scanner(System.in);
		System.out.println("나이를 입력하세요?");
		try {
			//nextInt()으로 나이받기
			//int age=sc.nextInt();	
			//nextLine()으로 나이받기
			String stringAge = sc.nextLine();
			int age = Integer.parseInt(stringAge);
			System.out.println("당신의 10년후 나이:"+(age+10));
		}
		catch(InputMismatchException | NumberFormatException e) {
			System.out.println("나이는 숫자만...");
		}
		/*
		[NullPointerException]:
		인스턴스 변수에 해당 객체의 메모리 주소가
		저장이 안된 경우에 .으로 객체의 멤버에 접근할때 발생		
		*/
		System.out.println(today);
		try {
			today.getTime();
		}
		catch(NullPointerException e) {
			System.out.println("today는 널입니다.포인터 할수 없어요");
		}
		/*
		  "":빈 문자열,null아님
		  null:null값. null이다
		 */
		String empty="";
		System.out.println("빈 문자열의 길이:"+empty.length());
		String nullStr= null;
		try {
			System.out.println("nullStr 문자열의 길이:"+nullStr.length());
		}
		catch(NullPointerException e) {
			System.out.println("nullStr은 널입니다");
		}
		/*
		 * [ArithmeticException]:
		 * 0으로 나눌때 발생
     	 */
		int result=100;
		try {
			result/=0;
			System.out.println("0으로 나눈 결과:"+result);
		}
		catch(ArithmeticException e) {
			//예외 메시지 출력방법]
			//1.사용자 임의 예외 메시지
			System.out.println("0으로 나눌 수 없어요");
			//2.예외 클래스의 인스턴스 변수 이용:e.toString() 
			//  "예외클래스 : 예외메시지"  형태를 문자열로 반환
			//System.out.println(e);
			//3.e.getMessage():예외메시지만 출력
			//System.out.println(e.getMessage());
			//4.e.printStackTrace();//개발시 주로 사용
			//e.printStackTrace();
		}
	}//////////main
	static Date today;

}/////////////class

sol)

'java' 카테고리의 다른 글

18일차 2023-03-31  (0) 2023.03.31
17일차 2023-03-30  (0) 2023.03.30
15일차 2023-03-28  (0) 2023.03.28
14일차 2023-03-27  (0) 2023.03.27
13일차 2023-03-24 Java  (0) 2023.03.24