본문 바로가기

웹 개발/Java

[Web_JAVA] 43

실습(총정리)

※ 문제

1. https://koreanname.me/ 접속
2. MVC 패턴을 사용하여 표(테이블)에 접근할 수 있는 클래스 선언
3. 2개의 테이블에 있는 데이터들을 각각 2개의 메모장에 붙여넣기
4. 2개의 메모장 파일을 한 개의 메모장 파일로 병합하기

※ 이름 수에 따른 랭킹을 새롭게 추가해준다.
※ 만약 이름 수가 동일하다면 공동 순위를 부여해준다.
※ 남자아이 이름은 맨 앞에 M을 추가하고, 여자아이 이름은 맨 앞에 F를 추가한다.
   예)  F   서연   1   35,647
        M   시우   7   26,027

남자아이 DAO
- 메모장의 데이터를 VO객체로 리턴하는 메소드 : setObject() 

여자아이 DAO
- 메모장의 데이터를 VO객체로 리턴하는 메소드 : setObject()

전체아이 DAO
1. 파일1과 파일2를 병합 : merge()
2. 병합된 파일에서 랭킹 수정(이름 수 순서 - 내림차순) : updateRanking()
※ 병합 시 두 개의 ArrayList를 하나의 ArrayList로 병합하는 방법
   ArrayList total = new ArrayList();
   ArrayList a = new ArrayList();
   ArrayList b = new ArrayList();

   total.addAll(a);
   total.addAll(b);

※ 중복된 이름 수 제거 : HashSet 사용
※ HashSet을 ArrayList로 변경
   HashSet set = new HashSet();
   ArrayList list = new ArrayList(set);

※ 동일한 이름 수일 경우 공동 순위로 구현한다.
예)
순위   이름 수
1   15000   15000
2   12000   12000
3   10000   10000
3   10000   8000
3   10000
6   8000

 

 

 

1. package vo

- ManVO.java

public class ManVO {
	
	// 이름
	private String name;
	
	// 순위
	private int ranking;
	
	// 인구 수
	private int population;
	
	public ManVO() {;}

	public String getName() { 
		return name;
	}

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

	public int getRanking() {
		return ranking;
	}

	public void setRanking(int ranking) {
		this.ranking = ranking;
	}

	public int getPopulation() {
		return population;
	}

	public void setPopulation(int population) {
		this.population = population;
	}

}

 

 

- WomanVO.java

public class WomanVO {

	private String name;
	private int ranking;
	private int population;
	
	public WomanVO() {;}

	public String getName() { 
		return name;
	}

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

	public int getRanking() {
		return ranking;
	}

	public void setRanking(int ranking) {
		this.ranking = ranking;
	}

	public int getPopulation() {
		return population;
	}

	public void setPopulation(int population) {
		this.population = population;
	}

}

 

 

- NamesDTO.java

import java.util.ArrayList;
import java.util.Collections;

public class NamesDTO {
	
	private String name;
	private int ranking;
	private int population;
	private char gender;  // 성별
	
	public NamesDTO() {;}

	public String getName() { 
		return name;
	}

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

	public int getRanking() {
		return ranking;
	}

	public void setRanking(int ranking) {
		this.ranking = ranking;
	}

	public int getPopulation() {
		return population;
	}

	public void setPopulation(int population) {
		this.population = population;
	}

	public char getGender() {
		return gender;
	}

	public void setGender(char gender) {
		this.gender = gender;
	}
	
	// toString() 재정의
	@Override
	public String toString() {
		String result = "";
		String population = this.population + "";
		ArrayList<String> datas = new ArrayList<>();

		// 하나씩 문자열로 저장("" + '1' + "" + '0' + "" + '0' + "" + '0')
		population.chars().forEach(c -> datas.add("" + (char)c)); 

		// 콤마를 붙이기 편하게 하기 위해 reverse()를 사용한다.
		Collections.reverse(datas);
		
		for (int i = 0; i < datas.size(); i++) {

			// i % 3 == 2 : 3의 배수
			// datas.size() != i + 1 → (ex) 100,000일 때 ,100,000이 되지 않아야 한다.
			if(i % 3 == 2 && datas.size() != i + 1) { 
				datas.add(i + 1, ",");
			}

		}
		
		Collections.reverse(datas); // 다시 뒤집어준다.
		
		for (int i = 0; i < datas.size(); i++) {
			result += datas.get(i);
		}
		
		String str = this.gender + "\t"
						+ this.name + "\t"
						+ this.ranking + "\t"
						+ result + "\n";
		return str;
	}
	
}

 

 

 

2. package dao

- DBConnecter.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class DBConnecter {
	
	// 외부에서 경로를 전달받은 후 알맞는 객체를 리턴해준다.
	
	public static BufferedReader getReader(String path) throws IOException {
		return new BufferedReader(new FileReader(path));
	}
	
	public static BufferedWriter getWriter(String path) throws IOException {
		return new BufferedWriter(new FileWriter(path));
	}
	
	public static BufferedWriter getAppend(String path) throws IOException {
		return new BufferedWriter(new FileWriter(path, true));
	}
 
}

 

 

- ManDAO.java

import vo.ManVO;

public class ManDAO {
	
	// 파일에 있는 내용 중 한 줄을 전달 받는다.
	public ManVO setObject(String data) {
		
		// 전달 받은 문자열을 \t로 구분하여 잘라준다.
		String[] datas = data.split("\t");
		ManVO man = new ManVO();
		
		// 각 정보를 모델 객체에 담아준다.
		man.setName(datas[0]);
		man.setRanking(Integer.parseInt(datas[1]));
		
		// 쉼표는 정수로 바꿀 수 없기 때문에 쉼표를 없애준다.
		man.setPopulation(Integer.parseInt(removeComma(datas[2])));
		
		return man;
	}
	
	// 콤마 지우기
	public String removeComma(String data) {
		return data.replaceAll(",", "");
	} 
	
}

 

 

- WomanDAO.java

import vo.WomanVO;

public class WomanDAO {
	public WomanVO setObject(String data) {

		String[] datas = data.split("\t");
		WomanVO woman = new WomanVO();
		
		woman.setName(datas[0]);
		woman.setRanking(Integer.parseInt(datas[1]));
		woman.setPopulation(Integer.parseInt(removeComma(datas[2])));
		
		return woman;
	}
	
	public String removeComma(String data) {
		return data.replaceAll(",", "");
	}

}

 

 

- NamesDAO.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;

import vo.ManVO;
import vo.NamesDTO;
import vo.WomanVO;

public class NamesDAO {
	
	// 남자 아이의 전체 정보를 담을 ArrayList 
	public ArrayList<ManVO> men;
	
	// 여자 아이의 전체 정보를 담을 ArrayList
	public ArrayList<WomanVO> women;
	
	// 병합
	// 외부에서 경로 3개를 전달받는다.
	// path1 : 기존 파일 경로 1
	// path2 : 기존 파일 경로 2
	// path3 : 병합된 내용을 출력할 경로
	public void merge(String path1, String path2, String path3) throws IOException{
		
		BufferedReader manReader = DBConnecter.getReader(path1);
		BufferedReader womanReader = DBConnecter.getReader(path2);
		
		// 문자열을 분리해서 모델 객체로 바꿔야 하기 때문에 필요하다.(setObject() 메소드를 사용하기 위해 필요하다.)
		ManDAO mDao = new ManDAO();
		WomanDAO wDao = new WomanDAO();
		
		String line = null;
		
		// 남자아이와 여자아이의 전체 정보를 문자열로 저장할 변수
		String temp = "";
		
		men = new ArrayList<>();
		women = new ArrayList<>();
		
		while((line = manReader.readLine()) != null) {

			// 남자아이 정보가 전부 누적되어 저장됨
			temp += line + "\n";  
			
			// 남자 정보는 men에 저장
			men.add(mDao.setObject(line));
		}
		manReader.close();
		
		while((line = womanReader.readLine()) != null) {

			// 남자아이의 모든 정보가 누적되어 있는 상태에서 여자아이 정보가 누적되어 저장됨
			temp += line + "\n";
			
			// 여자 정보는 women에 저장
			women.add(wDao.setObject(line));
		}
		womanReader.close();
		
		BufferedWriter bw = DBConnecter.getWriter(path3);
		
		// path3에 남자아이와 여자아이의 전체 정보를 출력한다.
		bw.write(temp);
		bw.close();
	}
	
	// 랭킹 수정
	// 병합된 파일의 경로를 전달 받는다.
	public void update(String path) throws IOException {
		
		// 남자아이와 여자아이의 전체 정보를 저장할 ArrayList
		ArrayList<Object> datas = new ArrayList<>();

		// 아이 이름 별 인구 수를 저장할 ArrayList
		ArrayList<Integer> populations = new ArrayList<>();

		// 중복되는 인구 수를 없애기 위한 HashSet
		HashSet<Integer> populationSet = null;
		
		// datas에 men과 women의 전체 내용을 합쳐준다.
		datas.addAll(men);
		datas.addAll(women);

		// 아이 이름 별 인구 수를 populations에 담아준다.
		// v : 남자아이 or 여자아이 한 명의 전체 정보
		men.stream().map(v -> v.getPopulation()).forEach(populations::add);
		women.stream().map(v -> v.getPopulation()).forEach(populations::add);
		
		// 중복을 제거한다.
		populationSet = new HashSet<>(populations);
		
		// 다시 ArrayList에 담아준다.(중복이 없어진 상태)
		populations = new ArrayList<>(populationSet);
		
		// 내림차순 정렬을 해준다.
		Collections.sort(populations);
		Collections.reverse(populations);
		
		// 순위는 1위부터 시작한다.
		int ranking = 1;

		// 내림차순 된 아이들의 정보를 문자열로 담아줄 변수
		String result = "";
		
		// 내림차순으로 정렬된 인구 수를 기준으로 반복을 진행한다.
		for (Integer population : populations) {
			
			// 공동 순위의 개수를 세어 준다.
			int count = 0;

			for (Object vo : datas) {  // 각 아이들의 정보만큼 반복한다.

				if(vo instanceof ManVO) {  // 만약 남자 아이라면
					ManVO data = (ManVO)vo;  // 다운 캐스팅 진행

					if(data.getPopulation() == population) {  // 아이의 인구 수와 내림차순 된 인구 수를 비교한다.
						NamesDTO sortedDatas = new NamesDTO();  // 해당 인구 수의 아이 정보를 담아줄 객체
						sortedDatas.setName(data.getName());
						sortedDatas.setRanking(ranking);
						sortedDatas.setPopulation(population);
						sortedDatas.setGender('M');  // 성별 추가
						
						result += sortedDatas;  // toString() 재정의를 통해 알맞는 형식의 문자열을 result에 담아준다.
						count++;  // 공동 순위 개수 증가
						
					}
				}

				if(vo instanceof WomanVO) {  // 만약 여자 아이라면
					WomanVO data = (WomanVO)vo;

					if(data.getPopulation() == population) {
						NamesDTO sortedDatas = new NamesDTO();
						sortedDatas.setName(data.getName());
						sortedDatas.setRanking(ranking);
						sortedDatas.setPopulation(population);
						sortedDatas.setGender('W');
						
						result += sortedDatas;
						count++;

					}
				}

			}
			
			// 만약 같은 순위의 개수가 1보다 크다면 다음 순위에 그 만큼을 더해준다.
			// (ex) {1 2 3 3 3 6}이 되어야 하는데 ranking은 {1 2 3 3 3 4}가 된다.
			// count - 1을 더해주어 공동 순위 다음 순위가 올바른 순위로 나오도록 한다.
			if(count > 1) {ranking += count - 1;}
			ranking++;
		}
		
		BufferedWriter bw = DBConnecter.getWriter(path);
		bw.write(result);
		bw.close();

	}

}

 

 

 

3. package view

- Test.java

import java.io.IOException; 

import dao.NamesDAO;

public class Test {
	public static void main(String[] args) throws IOException{
		
		NamesDAO dao = new NamesDAO();
		dao.merge("manNames.txt", "womanNames.txt", "names.txt");
		dao.update("names.txt");
		
	}
}

 

 

- 결과

{names.txt} 파일이 생성되며, {manNames.txt}와 {womanNames.txt} 내용이 합쳐진 후 각 정보의 맨 앞에 성별(M or F)이 붙어서 출력된다.

names.txt

 

 

 

'웹 개발 > Java' 카테고리의 다른 글

[Web_JAVA] 42  (0) 2022.03.28
[Web_JAVA] 41  (0) 2022.03.27
[Web_JAVA] 40  (0) 2022.03.26
[Web_JAVA] 39  (0) 2022.03.25
[Web_JAVA] 38  (0) 2022.03.24