Techit 4th 4th

Huisu·2023년 5월 11일
0

Techit

목록 보기
3/42
post-thumbnail

JAVA

Getter & Setter

클래스의 멤버 변수는 대부분 private으로 선언하게 된다. 오브젝트의 멤버 변수에 직접 접근하는 방법을 피하고 보안을 강화하기 위함이다. 따라서 이럴 경우 생성자를 통해 초기화하고 Getter라는 메소드를 통해 값을 읽어들이고, Setter라는 메소드를 통해 재설정할 수 있다.

public class User {
    private String name;
    private String phoneNumber; // "01012345678" --> 0없어짐
    private int age;

    public User(String name, String phoneNumber, int age) {
        this.name = name;
        this.phoneNumber = phoneNumber;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public int getAge() {
        return age;
    }

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

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
public class UserTest {
    public static void main(String[] args) {
        User user1 = new User("김미미", "01000000000", 19);
        System.out.println(user1.getName());
        user1.setName("김나나");
        System.out.println(user1.getName());
    }
}

CodeUp 1308

정올 참여 학생 리스트 만들기 1

문제
세종이는 주말에 정보 과학실에서 정보 올림피아드 준비를 하려고 한다. 선생님은 정보 과학실 사용 조건으로 정보 올림피아드 참가 학생 명단을 작성하는 프로그램을 작성하라고 하셨다. 짖굳은 선생님은 입력 데이터를 만들 때 일부러 중간에 잘못된 값을 끼워 왕창 끼워 넣었다. 그리고 잘못된 데이터를 제거하는 방법을 설명해 주었다. 다음 조건에 따라 프로그램을 만들고 올바른 명단만 출력해 보자.

입력
첫째 줄에 입력 데이터의 개수 n이 입력된다. (10<=n<=100) 둘째 줄부터 n+1번째 줄까지 처리 코드c(문자 1자리), 수험 번호 no(1<=no<=10,000), 이름(10바이트 이내)이 입력된다. 처리 코드에 따라 입력 데이터를 메모리에 저장하거나 삭제해야 한다. 처리 코드가 'I'이면 데이터를 수험 번호 순서에 맞게 삽입한다. 만약 입력할 때 이미 수험 번호가 입력되어 있다면 아무 작업도 하지 않는다.처리 코드가 ‘D’이면 메모리의 데이터 중에서 해당 수험 번호를 찾아 삭제한다. 만약 처리 코드가 'D'이고 해당 수험 번호가 존재하지 않으면 아무 작업도 하지 않는다. 마지막으로 n+2번째 줄에 올바른 데이터의 위치를 나타내는 정수 5개가 입력된다.

출력
메모리에 저장된 데이터 중에서 올바른 데이터 위치에 있는 값의 명단을 출력한다.

입력된 code, testId, name 을 하나의 객체로 저장해 관리하는 것이 편하기 때문에, 이에 대한 클래스를 생성하고 생성자와 Getter & Setter를 만들어 준다.

class Student {
    private String code;
    private int testId;
    private String name;

    public Student(String code, int testId, String name) {
        this.code = code;
        this.testId = testId;
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public int getTestId() {
        return testId;
    }

    public String getName() {
        return name;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public void setTestId(int testId) {
        this.testId = testId;
    }

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

삽입 연산을 할 때 학생을 만들고 학생 리스트 안에 중복되는 값이 있는지 testId를 통해 검사하고 학생 리스트 안에 학생을 추가하는 동작이 필요하다. 이 연산이 반복되기 때문에 이를 따로 빼내어 메소드로 만든다. 출력하고 삭제하는 것 역시 개별적인 동작이기 때문에 메소드로 빼낸다.

public Student makeAStudent(String code, int testId, String name) {
        return new Student(code, testId, name);
    }

private boolean isExisted(Student pStudent) {
        // 중복 여부 check
        for (Student student : students){
            if(pStudent.getTestId() == student.getTestId()){
                return true;
            }
        }
        return false;
    }

private void addStudent(Student student) {
        if (!isExisted(student)) {
            students.add(student);
        }
    }

private void deleteStudent(Student pstudent) {
        for (int i = 0; i < students.size(); i++) {
            if(students.get(i).getTestId() == pstudent.getTestId()) students.remove(i);
        }
    }

code에 따라 삽입할 것인지 삭제할 것인지를 나타내는 과정도 독립적으로 빼서 작성한다.

public void process(Student pstudent) {
        switch (pstudent.getCode()){
            case "I" -> addStudent(pstudent);
            case "D" -> deleteStudent(pstudent);
        }
    }

특정 index만 출력하게 하는 함수를 따로 만들어서 작성한다.

private void printSpecificStudents(int[] arr) {
        // 정렬
        Collections.sort(students,new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getTestId() - o2.getTestId();
            }
        });
        for (int i = 0; i < arr.length; i++) {
            Student student = students.get(arr[i] - 1);
            System.out.printf("%d %s\n", student.getTestId(), student.getName());
        }
    }

입력값 받아 실행하는 main을 만든다.

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int number = sc.nextInt();
        CodeUp3108 codeUp3108 = new CodeUp3108();
        for (int i = 0; i < number; i++) {
            String code = sc.next();
            int testId = sc.nextInt();
            String name = sc.next();
            Student student = codeUp3108.makeAStudent(code, testId, name);
            codeUp3108.process(student);
        }
        int[] index = new int[5];
        for (int i = 0; i < 5; i++) {
            index[i] = sc.nextInt();
        }
        codeUp3108.printSpecificStudents(index);
    }

전체 코드는 다음과 같다.

import java.util.*;

class Student {
    private String code;
    private int testId;
    private String name;

    public Student(String code, int testId, String name) {
        this.code = code;
        this.testId = testId;
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public int getTestId() {
        return testId;
    }

    public String getName() {
        return name;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public void setTestId(int testId) {
        this.testId = testId;
    }

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

public class CodeUp3108 {
    private List<Student> students = new ArrayList<>();
    public Student makeAStudent(String code, int testId, String name) {
        return new Student(code, testId, name);
    }
    private boolean isExisted(Student pStudent) {
        // 중복 여부 check
        for (Student student : students){
            if(pStudent.getTestId() == student.getTestId()){
                return true;
            }
        }
        return false;
    }
    private void addStudent(Student student) {
        if (!isExisted(student)) {
            students.add(student);
        }
    }

    private void deleteStudent(Student pstudent) {
        for (int i = 0; i < students.size(); i++) {
            if(students.get(i).getTestId() == pstudent.getTestId()) students.remove(i);
        }
    }

    public void process(Student pstudent) {
        switch (pstudent.getCode()){
            case "I" -> addStudent(pstudent);
            case "D" -> deleteStudent(pstudent);
        }
    }

    private void printSpecificStudents(int[] arr) {
        // 정렬
        Collections.sort(students,new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getTestId() - o2.getTestId();
            }
        });
        for (int i = 0; i < arr.length; i++) {
            Student student = students.get(arr[i] - 1);
            System.out.printf("%d %s\n", student.getTestId(), student.getName());
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int number = sc.nextInt();
        CodeUp3108 codeUp3108 = new CodeUp3108();
        for (int i = 0; i < number; i++) {
            String code = sc.next();
            int testId = sc.nextInt();
            String name = sc.next();
            Student student = codeUp3108.makeAStudent(code, testId, name);
            codeUp3108.process(student);
        }
        int[] index = new int[5];
        for (int i = 0; i < 5; i++) {
            index[i] = sc.nextInt();
        }
        codeUp3108.printSpecificStudents(index);
    }

}

FileParse

위 Codeup 1308 의 경우 I 999 백두산을 Student라는 객체로 저장해서 문제를 풀이한다. 이런 과정을 parsing이라고 한다.

Parsing
String type으로 되어 있는 데이터를 자바의 Object type으로 바꿔 만드는 행위이다. 이렇게 파싱을 하면 iterator를 사용할 수 있고, 접근제어자를 사용해 자바의 연산을 사용할 수 있다는 장점이 있다. 하나의 큰 String으로 저장할 때보다 객체 타입으로 저장하고 있을 때 검색, 중복 체크 등의 다양한 기능 확장이 가능해진다.

건강보험심사평가원_전국 병의원 및 약국 현황_20230331

공공 데이터 포털에서 제공하는 전국 병의원 및 약국 현황 데이터를 읽어서 파싱하는 작업을 진행하면 다음과 같다. 데이터는 위 사이트에서 다운로드받을 수 있다.

다운로드받은 파일을 열어 보면 위와 같은 여러 칼럼들이 존재하는데, 이중 이름, 연락처, 주소를 받아와서 자바의 객체로 저장하는 파싱 작업을 진행하고자 한다. 이를 위해 Hospital이라는 객체를 만들어 생성자까지 만든 코드는 다음과 같다.

public class Hospital {
    String name;
    String phoneNumber;
    Address address;

    public Hospital(String name, String phoneNumber, Address address) {
        this.name = name;
        this.phoneNumber = phoneNumber;
        this.address = address;
    }
}

이때 주소의 경우 시, 읍, 동 등 다양한 요소가 결합되어 있기 때문에 주소를 하나의 String으로 관리하는 것이 아니라 주소라는 객체로 따로 저장해 관리하는 것이 더욱 용이할 수 있다. 따라서 주소를 따로 저장하는 Address 클래스를 생성한다.

public class Address {
    String city;
    String street;
}

프로젝트 디렉토리에 위 엑셀 파일을 저장한 뒤, BufferedReader를 통해 읽어들인다. 이때 FileReader라는 자바 지원 클래스를 사용한다.

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ReadFileEx {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("./hospital_info.csv"));
        System.out.println(br.readLine());
    }
}

Collections

Collections
여러 개의 자료를 넣을 수 있는 자료 구조의 자바 구현체이다. Array 보다 편의 기능을 제공하는 자료 저장 객체라고 생각하면 된다.

List

Array는 선언할 때 길이를 고정시키지만 List 같은 경우는 길이를 자동으로 조정해 준다. 한 리스트 안에는 다양한 자료형의 요소들이 들어갈 수 있으며, 추가와 삭제를 진행할 때마다 길이를 자동으로 조절한다.

add(item): 리스트에 아이템 추가

get(index): 인덱스에 해당하는 리스트 아이템 반환

remove(index): 인덱스에 해당하는 리스트 아이템 삭제

isEmpty(): 리스트가 비어 있는지 boolean 값 반환

import java.util.ArrayList;
import java.util.List;

public class ListEx {
    public static void main(String[] args) {
        List l1 = new ArrayList();
        l1.add("Hello");
        l1.add(1);
        System.out.println(l1.get(0));
        System.out.println(l1.get(1));
        System.out.println(l1.size());
        System.out.println(l1.isEmpty());
        l1.remove(0);
        l1.remove(0);
        System.out.println(l1.isEmpty());
    }
}
Hello
1
2
false
true

List 자료 구조에서는 iterator를 지원한다. iterator는 for문을 사용할 수 있는, 반복할 수 있는 변수이다. 간단하게 repeator라고 생각하면 된다. iterator를 사용하여 리스트를 순회하는 문법을 for each라고 하며, 다음과 같이 구현할 수 있다.

for(var item : l1) { //for each
            System.out.println(item);
        }

자바는 강타입 언어라서 형식을 지정해 줘야 하지만, var 같은 경우는 문자열인 Hello도 출력하고, 1인 int도 출력한다. 이렇게 타입에 구애받지 않도록 클래스를 구현해 놓는 것을 Generic 문법이라고 한다. 기본적인 리스트는 내용물로 다양한 요소가 들어갈 수 있다. 하지만 이렇게 리스트를 구현할 경우 메모리를 많이 사용하고 일관적인 연산이나 계산이 불가능하다. 따라서 타입을 지정해 주는 경우가 잦은데, List으로 타입을 결정해 주면 그때는 해당 타입의 요소만 넣을 수 있다.

List l1 = new ArrayList(); // 메모리를 많이 사용하고 일관적으로 사용 불가능
List<Integer> l2 = new ArrayList<>();

Generic을 사용할 경우 for each 구문이 더욱 명료해진다.

public class GenericEx {
    public static void main(String[] args) {
        List<String> strList = new ArrayList<>();
        strList.add("hello");
        strList.add("bye");

        List<Integer> intList = new ArrayList<>();
        intList.add(1);
        intList.add(2);

        for(String item : strList) {
            System.out.println(item);
        }

        for(int item : intList) {
            System.out.println(item);
        }
    }
}

Generic을 사용하지 않으면 해당 타입에서만 사용할 수 있는 다양한 함수들을 사용할 수 없어서 불편하다. 예를 들어 String의 split() 메소드를 사용하고 싶을 때, 리스트의 요소들의 타입이 예상되지 않으면 해당 함수를 사용할 수 없다.

for(var item : l1){
   System.out.println(item.split()); // 사용불가
}

0개의 댓글