알고리즘
최대값 구하기
최대값 I
최대값 2
다형성을 적용하여 최대값과 최소값을 구하는 로직
템플릿 콜백 패턴
Intellij의 단축키
DB
•
SQL INSERT script logic (서울시 병의원 위치정보 파일 활용)
•
Java로 .sql 파일 만들기
알고리즘
문제 1. 최대값 구하기
9개의 서로 다른 자연수가 주어질 때, 이들 중 최대값을 찾고 그 최대값이
몇 번째 수인지를 구하는 프로그램을 작성하시오.
예를 들어, 서로 다른 9개의 자연수 3, 29, 38, 12, 57, 74, 40, 85, 61이
주어지면 이들 중 최대값은 85이고, 이 값은 8번째 수이다.
Java
복사
package lecture.lectrue_1012;
/**
* 코드업 2081
*/
public class Max01 {
public void getMax(int[] arr){
int max = 0;
int maxIdx = 0;
for(int i = 1;i < arr.length; i++){
if (arr[i] > max){
max = arr[i];
maxIdx = i;
}
}
System.out.println(max);
System.out.println(maxIdx);
}
public static void main(String[] args) {
int arr[] = new int[]{3, 29, 38, 12, 57, 74, 40, 85, 61};
Max01 max = new Max01();
max.getMax(arr);
}
}
Java
복사
•
위 로직에는 문제점이 존재합니다.
max 값을 0으로 초기화 하게 되면, 비교 대상이 되는 배열인 arr의 값들이 모두 음수인 경우 항상
0보다 작게 되어서 루프를 모두 돌아도 max값이 0이 될 것이기 때문입니다.
Java
복사
•
따라서 max값을 배열의 첫번째 값으로 초기화 해주고, 나머지 요소들과 비교하도록 해주어야 합니다.
수정 로직
package lecture.lectrue_1012;
/**
* 코드업 2081
*/
public class Max01 {
public void getMax(int[] arr){
int max = arr[0]; 배열의 첫번째 값으로 max값 초기화
int maxIdx = 0;
for(int i = 1;i < arr.length; i++){
if (arr[i] > max){
max = arr[i];
maxIdx = i;
}
}
System.out.println(max);
System.out.println(maxIdx);
}
public static void main(String[] args) {
int arr[] = new int[]{3, 29, 38, 12, 57, 74, 40, 85, 61};
Max01 max = new Max01();
max.getMax(arr);
}
}
Java
복사
강사님 코드
2. 최댓값 구하기ll
•
이 문제의 경우 9*9 크기의 2차원 배열을 생성할 수 있어야 한다.
package lecture.lectrue_1012;
import java.util.Arrays;
public class Max02 {
public void getMax(int arr[][]){
int maxValue = arr[0][0];
int maxIdx[] = new int[]{0,0};
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int a = arr[i][j]; // j가 먼저 바뀐다.
//j가 0~9까지 한번씩 돌아감
if (arr[i][j] > maxValue){
maxValue = arr[i][j];
maxIdx[0] = i;
maxIdx[1] = j;
}
}
}
System.out.println(maxValue);
System.out.println(maxIdx[0] + " " + maxIdx[1]);
}
public static void main(String[] args) {
int arr[][] = new int[][]{
{3, 23, 85, 34, 17, 74, 25, 52, 65},
{10, 7, 39, 42, 88, 52, 14, 72, 63},
{87, 42, 18, 78, 53, 45, 18, 84, 53},
{34, 28, 64, 85, 12, 16, 75, 36, 55},
{21, 77, 45, 35, 28, 75, 90, 76, 1},
{25, 87, 65, 15, 28, 11, 37, 28, 74},
{65, 27, 75, 41, 7, 89, 78, 64, 39},
{47, 47, 70, 45, 23, 65, 3, 41, 44},
{87, 13, 82, 38, 31, 12, 29, 29, 80}
};
Max02 max02 = new Max02();
max02.getMax(arr);
}
}
Java
복사
•
2차원 배열 진행 순서
◦
arr[i][j] = 열 (세로) 순회
◦
arr[j][i] = 행 (가로) 순회
•
코드를 만들기 전에 위와 같이 프로그램이 동작하는 것을 생각해보고, 코드를 설계하는 단계를 거치자
◦
바로 키보드로 코드를 짜는 것은 잘못된 것. (생각하고 코드를 짜자)
•
공간 복잡도 vs 코드 가독성
◦
알고리즘 문제, 속도 - 공간 복잡도가 조금 더 중요
◦
협업 - 코드 가독성이 더 중요
다형성을 적용하여 최댓값과 최솟값을 구하는 로직
•
템플릿/ 콜백 패턴
◦
전략 패턴의 변형으로 DI(Dependency Injection) 의존성 주입에서 사용하는 특별한 전략 패턴
◦
전략 패턴에 익명 내부 클래스를 더해서 사용하는 방법
•
아래 코드를 보며 이해해보자.
package lecture.lectrue_1012;
interface Compare{
boolean doSomeThing(int a, int b);
}
public class MaxAndMin {
private int getMaxorMin(int arr[], Compare compare){
int targetValue = arr[0];
for(int i = 0;i<arr.length;i++){
boolean isSth = compare.doSomeThing(arr[i], targetValue);
if(isSth){
targetValue = arr[i];
}
}
return targetValue;
}
public int max(int[] arr){
return getMaxorMin(arr, new Compare(){
@Override
public boolean doSomeThing(int a, int b) {
return a>b;
}
});
}
public int min(int [] arr){
return getMaxorMin(arr, new Compare() {
@Override
public boolean doSomeThing(int a, int b) {
return a<b;
}
});
}
}
Java
복사
public static void main(String[] args) {
int arr[] = new int[]{3, 23, 85, 34, 17, 74, 25, 52, 65};
MaxAndMin m = new MaxAndMin();
int max = m.max(arr);
int min = m.min(arr);
System.out.println(max);
System.out.println(min);
}
Java
복사
템플릿/콜백 패턴 적용 부분
private int getMaxorMin(int arr[], Compare compare){
int targetValue = arr[0];
for(int i = 0;i<arr.length;i++){
boolean isSth = compare.doSomeThing(arr[i], targetValue);
if(isSth){
targetValue = arr[i];
}
}
return targetValue;
}
public int max(int[] arr){
return getMaxorMin(arr, new Compare(){
@Override
public boolean doSomeThing(int a, int b) {
return a>b;
}
});
}
public int min(int [] arr){
return getMaxorMin(arr, new Compare() {
@Override
public boolean doSomeThing(int a, int b) {
return a<b;
}
});
}
Java
복사
•
템플릿 콜백 패턴이 적용된 코드입니다.
•
getMaxorMin() 인자에 Interface의 구현체 주입을 클래스 내부에서 수행 하는 것을 볼 수 있습니다.
◦
전략 패턴 : 변화되는 부분을 매번 클래스로 만들고 외부에서 구체 클래스를 주입해주는 형식
◦
위의 예제의 경우, MaxCompare 클래스와 MinCompare 과 같은 비교 방식을 구현하는 두 개의 구현체 클래스를 만들고, 외부 (메인 메소드)에서 구체 클래스를 주입해주어야 할 것입니다.
•
템플릿 : 정해져 있는 틀, 콜백 : 다른 코드의 인수로서 넘겨주는 실행 가능한 코드
작동 순서
Intellij 단축키
ctrl+alt+l | 코드 정렬 |
ctrl+shift+8 | 모드 바꾸기 |
shift + 위아래 방향키 | 멀티 마우스 커서 |
ctrl + g | 같은 단어 찾기 |
alt+insert | Project 구조에서 새로운 파일 생성 |
SQL INSERT 스크립트 로직
활용 데이터 : 서울시 병의원 위치 정보
요구사항
1.
병원분류명의 총 개수는 얼마인가?
2.
병원분류별로 몇개씩 있는지 ? ex. 의원:x개, 치과 병원: y개, 한방병원: z개..
3.
병원 분류가 몇가지 인지?
4.
서울의 구별로 각 병원이 몇개 있는지? ex. 서울시 금천구 의원, 한방 병원, 치과 병원 ..이 각 몇개인지?
5.
구별로 병원이 가장 많은 구는?
6.
이비인후과(0), 외과(1), 내과(2), 소아과(3), 피부과, 성형외과는 각 몇개인지? (category)
요구사항 분석 : 고객이 무엇을 원하는지 분석한다.
개념적 설계 : ERD 작성과 같은 것
논리적 설계 : 테이블 정의서를 작성하는 단계
물리적 설계: 개념적 설계와 논리적 설계의 산출물을 바탕으로 테이블을 생성하는 단계
논리적 설계 단계 - 테이블 정의서 작성
서울 특별시_ 병의원
seoul_hospital
컬럼명 | 설명 | TYPE | ex |
id(PK) | VARCHAR(8) | A11200837 | |
address | 전체 주소 | VARCHAR(30) | 서울 특별시 서초구 역삼동…. |
district | 서울시 00구 | VARCHAR(15) | 서울특별시 서초구 |
category | 병원 분류 C의원, E 한방병원 등… | VARCHAR(1) | |
emergency_room | 응급실 운영여부 (1/2) | INT | 1 또는 2 |
name | 기관명 | VARCHAR(40) | 강남하이텍의원 |
subdivision | 세부 분과(피부과, 성형외과, 외과 ,내과 등) | VARCHAR(10) | 비뇨기과 피부과 성형외과 외과 내과 등 |
물리적 설계
Entity(Table) seoul_hospital에 1개 Row(Record) 삽입하기
INSERT INTO `likelion-db`.`seoul_hospital`
(`id`,
`address`,
`district`,
`category`,
`emergency_room`,
`name`,
`subdivision`)
VALUES
('A1120837',
'서울특별시 금천구 벚꽃로 286 삼성리더스타워 111~114호 (가산동)',
'서울특별시 금천구',
'C',
2,
'가산기대찬의원',
null);
SQL
복사
파일을 활용하여 SQL문 작성하기
1.
sublime txt를 활용하여 sql문 작성
2.
.sql로 스크립트 파일 저장
3.
Workbench에서 .sql 스크립트 불러오기
4.
불러온 .sql 스크립트 실행
•
insert into 구문은 PK 값이 다르면, insert 할 각 데이터마다 “insert into” 문자열을 붙혀주지 않아도 된다.
INSERT INTO `likelion-db`.`seoul_hospital`
(`id`,`address`,`district`,`category`,`emergency_room`,`name`,`subdivision`)
VALUES
('B1100027','서울특별시 강남구 도산대로 118 (논현동 신사빌딩 2층)
','서울특별시 강남구','C',2,'365엠씨의원',null),
('A1117873','서울특별시 강남구 도산대로 118 (논현동 신사빌딩 2층)
','서울특별시 강남구','C',2,'365엠씨의원',null)
;
SQL
복사
Java로 .sql 파일 만들기
요구사항
•
서울시 병의원 정보가 들어 있는 .csv 파일을 읽어서 seoul_hospital_insert.sql을 작성하는 코드를 만들어보세요.
1.
파일 만들기
2.
.csv에서 line 별로 읽어오기 (”,”)로 끊어줌
3.
JavaObject Hospital() → 도메인
4.
line 별로 읽어와서 필요한 정보만 뽑아 Object에 담기 - ex. setSubDivision()
5.
생성자에서 setDistrict() 호출
a.
ex. 서울특별시 강남구 와 같은 형태이므로 addressSplit[0] + “ ” + addressSplit[1]과 같은 형태로 만들어낼 수 있다.
6.
subdivision은 병원 이름(name)을 기준 (, 등) - 이 단어가 포함되어 있으면 ..
ex ) 피부과가 포함되어 있으면 피부과
외과가 포함되어 있으면 외과
로직 구축
package org.example.parser;
//병원정보, 인구 정보를 읽느냐에 따라서 파싱 정보가 달라질 수도 있음
-> 구현체만 바꿔 끼워주면 된다.
public interface Parser <T>{
T parse(String fileContents); //parse()메소드 하나 선언
}
Java
복사
package org.example.parser;
import org.example.domain.Hospital;
public class HospitalParser implements Parser<Hospital>{
@Override
public Hospital parse(String fileContents) {
String[] split = fileContents.split(",");
return new Hospital(split[0]);
}
}
Java
복사
package org.example;
import org.example.parser.Parser;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class LineReader<T> {
private Parser<T> parser;
boolean isRemoveFirstLine = true; //flag 변수
public LineReader(Parser<T> parser) {
this.parser = parser;
}
public List<T> readFiles(String filename) throws IOException {
List<T> file = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader(filename));
String str;
if(isRemoveFirstLine){
br.readLine(); //첫줄은 컬럼명이라 일단 허공에 이런식으로 날려줌.
}
while((str = br.readLine()) != null){
file.add(parser.parse(str));
}
return file;
}
}
Java
복사
package org.example;
import org.example.domain.Hospital;
import org.example.parser.HospitalParser;
import java.io.IOException;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
LineReader<Hospital> lr = new LineReader<Hospital>(new HospitalParser()); //구현체 주입 -> 다형성 적용
String fileName = "C:\\users\\cmkxak\\Downloads\\서울시 병의원 위치 정보.csv"; //서울시 병의원 위치 정보
List<Hospital> hospitalFile = lr.readFiles(fileName);
//file size
System.out.println(hospitalFile.size());
//hospital id
for (Hospital hospital : hospitalFile) {
System.out.println(hospital.getId());
}
}
}
Java
복사
•
메인 메소드에서 LineReader 객체 생성 시, HospitalParser() 객체를 생성하도록 합니다.
◦
따라서, lr 이라는 변수명을 가진 객체는 HospitalParser 구현체의 parse() 메소드 기능을 사용할 수 있습니다.
•
위와 같은 구조는, 인터페이스를 활용하여 다양한 구현체 클래스를 만들어주는 형태입니다.
•
이는 파일을 읽는 로직인 readFiles()의 수정 없이,
parse() 메소드의 구현 클래스를 다르게 적용해줌으로써,
파일을 읽을 경우 파싱해주는 작업이 각기 다양하게 작동하는 것과 같이 기능의 확장을 가능하게 해줍니다. → OCP(Open-Closed Principle, 개방 폐쇄의 원칙)