실습(총정리)
※ 문제
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)이 붙어서 출력된다.

'웹 개발 > 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 |