ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA] 개발자 지망생 스터디 - 31일차
    스터디/KAKAOCLOUDSCHOOL 2022. 12. 14. 15:53

    8. 논리 연산자

    1) 조건 논리 연산자


    2) 비트 논리 연산자

    > 정수 데이터를 가지고 연산을 수행하는데 비트 단위로 논리 연산을 수행한 후 정수로 결과를 리턴
    ~ : 단항 연산자로 1의 보수를 리턴하는 연산자
    & : and 연산자로 둘 다 1인 경우만 1
    | : or 연산자로 둘 다 0 인 경우만 0
    ^ : eXclusive OR 로 같으면 0 다르면 1

    20 : 00000000 00000000 00000000 00010100
    17 : 00000000 00000000 00000000 00010001

    20 &  17 : 000000000 00000000 00000000 0001000 => 16
    20 | 17 : 00000000 00000000 00000000 00010101 => 21
    20 ^ 17 : 00000000 00000000 00000000 00000101 => 5

    public class BitLogical {
        public static void main(String[] args) {
            int n1 = 20;
            int n2 = 17;
            System.out.println(n1 & n2); //16
            System.out.println(n1 | n2); //21
            System.out.println(n1 ^ n2); //5
        }
    }​

    9. 삼항 연산자

    #기본 형식
    > 조건식 ? 조건식이 true 일 때 남는 식 : 조건식이 false 일 때 남는 식
    > 자바는 조건식은 반드시 boolean을 리턴해야 함

    10. 할당 연산자

    = : 오른쪽의 데이터를 왼쪽의 변수가 가리키도록 하는 연산자
    연산자 = : 왼쪽의 데이터와 오른쪽의 데이터를 연산자를 이용해서 연산을 수행
    그 결과를 왼쪽의 변수가 가리키도록 하는 연산자임

    int a = 10;
    a += 20;
    System.out.println(a); // a = a + 20; result = 30

    > 변수의 값을 1 증가시키는 방법
    a++; // 이 방법이 속도가 가장 빠르다고 함
    a+=1;
    a = a + 1; // 이 방법이 제일 느림

    11. 문자열의 + 연산자

    > 문자열은 모든 데이터와 + 연산이 가능
    > 기본형 데이터의 경우는 문자열로 형 변환을 해서 결합을 하고 나머지 데이터는 toString 메서드를 호출해서 그 결과를 결합하는 방식을 취하게 됨
    > 문자열 리터럴은 static 영역에 저장되기 때문에 내용 변경이 안됨
    문자열을 + 로 결합을 하게 되면 메모리 낭비가 발생할 수 있음
    문자열 + 연산을 자주 사용하지 않는 것을 권장하고 String.format 이나 StringBuilder를 사용하는것을 권장함
    Java 1.7 버전 부터는 문자열의 + 연산을 자바가 내부적으로 StringBuilder를 이용해서 수행하기 때문에 크게 관계 없음

    제어문(ControlStatement)

    1. java에서의 import

    > java는 애플리케이션을 실행하면 JDK가 제공하는 클래스들은 JRE가 제공해주고 우리가 만든 모든 클래스를 JVM에 로딩을 해서 실행을 함
    > 근본적으로 자바에서는 import 과정이 필요 없음
    > java에서 import 는 메모리를 가져오는 개념이 아니고 줄여쓰기 위한 개념임

    import java.util.BufferedReader;
    앞으로 BufferedReader라고 쓰면 java.util.BufferedReader를 사용한다라는 의미임

    import java.util.*;
    java.util 패키지에 있는 모든 클래스를 줄여쓰기를 하겠다는 의미임

    2. 콘솔에서 입력받기

    1) java.io.BufferedReader 클래스 이용

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String str = br.readLine(); // 한 줄의 문자열을 입력받아서 str에 대입​
    > 이 방법은 예외 처리를 강제함

    2) java.util.Scanner 클래스 이용

    Sccaner sc = new Scanner(System.in);
    자료형 변수이름 = sc.next자료형(); //문자열을 받아서 자료형으로 변환한 후 리턴
    #실습
    package kakao.itoriginal.controlstatement;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.nio.Buffer;
    import java.util.Scanner;
    
    public class ConsoleInput {
        public static void main(String[] args) {
            /*
            //BufferedReader를 이용한 숫자 와 문자열 입력받기
            try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
                System.out.print("이름을 입력하세요:");
                //한 줄의 문자열 입력받기
                String str = br.readLine();
                System.out.println(str);
                System.out.print("나이를 입력하세요:");
                String age = br.readLine();
                //age라는 문자열을 정수로 변환
                int nai = Integer.parseInt(age);
                System.out.println(nai);
            } catch (Exception e) {
                System.out.println(e.getLocalizedMessage());
            }
            */
    
            try (Scanner sc = new Scanner(System.in)) {
                System.out.println("나이를 입력하세요:");
                int age = sc.nextInt();
    
                System.out.print("이름을 입력하세요:");
                //숫자를 입력받고 문자열을 입력 받는 경우에는
                //앞에 입력한 Enter를 제거하기 위해 한 번 더 호출
                sc.nextLine();
                String name = sc.nextLine();
                System.out.println(name + ":" + age);
            } catch (Exception e) {
                System.out.println(e.getLocalizedMessage());
            }
        }
    }​
    💡 NS CHART
    http://itnovice1.blogspot.com/2019/08/nsnassi-schneiderman.html
    💡FLOW CHART
    https://blog.naver.com/PostView.nhn?blogId=ycpiglet&logNo=222113989214&from=search&redirect=Log&widgetTypeCall=true&directAccess=false
     

    플로우차트란 무엇인가? (흐름도, 순서도) / 기호 설명과 그리는 방법, 주의사항 (알고리즘, Algorit

    플로우차트란? 플로우차트(Flowchart)는 순서도, 흐름도라고도 한다. 순서도는 어떠한 일을 처리하는 과정...

    blog.naver.com

     

    [소프트웨어공학] NS(Nassi-Schneiderman) 차트

    [소프트웨어공학] NS(Nassi-Schneiderman) 차트 NS(나씨 슈나이더만) 차트 모듈 명세서를 글로 쓸수도 있지만 N-S차트로 그림으로 그릴 수 있다. 플로우차트는 생각보다는 사용횟수가 많지 않다.  손으

    itnovice1.blogspot.com

    3. if

    표현식 : 변수 상수(리터럴은 제외), 연산식, 메서드 호출 구문

    1) 기본 형식

    if(boolean이 나오는 표현식){
    	표현식이 true일 때 수행할 내용
    }else if(boolean이 리턴되는 표현식){
    	앞의 표현식이 false이고 표현식이 true 일 때 수행할 내용
    }...
    else{
    	앞의 모든 표현식이 false일 때 수행할 내용
    }​
    > if는 필수이며, 1번만 나와야 함
    > else if는 0번 이상 여러 번 작성이 가능함
    > else if를 만들 때 주의할 점은 dead code(결코 수행되지 않는 code) 조건을 만들면 안됨
    > else 는 0번 이나 1번만 작성
    > else if 와 else 가 같이 사용되는 경우에는 else 에서 예외적인 상황을 처리해주는 것이 좋음
    예전 try ~ catch 가 없을 때 else를 가지고 예외처리를 했음

    2) 기본 코드 예제

    #점수를 입력받아서 60이 넘으면 합격 아니면 불합격을 출력

    import java.util.Scanner;
    
    public class PassIf {
        public static void main(String[] args) {
            try(Scanner sc = new Scanner(System.in)){
                System.out.println("점수 입력 : ");
                int score = sc.nextInt();
                if (score >= 60){
                    System.out.println("축하합니다! 합격 입니다!");
                }else {
                    System.out.println("안타깝게도 불합격 입니다.");
                }
            }catch (Exception e){
                System.out.println(e.getLocalizedMessage());
            }
        }
    }​


    # 점수를 입력받아서 90점 이상이면 A 80점 이상이면 B 70점 이상이면 C 60점 이상이면 D 그 이하는 F

    import java.util.Scanner;
    public class PassIf {
        public static void main(String[] args) {
            try(Scanner sc = new Scanner(System.in)){
                System.out.print("점수 입력 : ");
                int score = sc.nextInt();
                if (score >= 90 && score <= 100){
                    System.out.println("A");
                }else if(score >= 80 && score < 90){
                    System.out.println("B");
                }else if(score >= 70 && score < 80){
                    System.out.println("C");
                }else if(score >= 60 && score < 70){
                    System.out.println("D");
                }else if(score >= 0 && score < 60){
                    System.out.println("F");
                }else {
                    System.out.println("잘못된 점수를 입력하셨습니다.");
                }
            }catch (Exception e){
                System.out.println(e.getLocalizedMessage());
            }
        }
    }


    #ID와 PassWord를 입력 받아서 ID가 "root"이고 PassWord 가 "1234" 이면 로그인 성공 그렇지 않으면 로그인 실패 출력

    import java.util.Scanner;
    public class PassIf {
        public static void main(String[] args) {
            try(Scanner sc = new Scanner(System.in)){
                System.out.print("ID를 입력하세요 : ");
                String id = sc.nextLine();
                System.out.print("PW를 입력하세요 : ");
                String password = sc.nextLine();
                //문자열은 생성 방법에 따라 다른 인스턴스가 될 수 있어서 값이 동일한 지 비교할 때
                //==를 사용하면 안되고 equals 메서드를 이용하여 동일성 여부를 비교
                if(id.equals("root") && password.equals("1234")){
                    System.out.println(id+"님 환영합니다");
                }else{
                    System.out.println("잘못된 정보입니다.");
                }
    
            }catch (Exception e){
                System.out.println(e.getLocalizedMessage());
            }
        }
    }​

    4. switch ~ case

    1) 기본 구조

    switch(정수나 문자열 표현식):
    	case 값1:
        	값1 일 때 수행할 내용;
            (break;)
    	case 값2:
        	값2 일 때 수행할 내용;
            (break;)
    	...
    	default:
        	수행할 내용;
            (break;)
    }​
    > 값에 의한 분기
    > 사용 가능한 데이터는 정수와 문자열
    > case의 개수는 제한 없음
    > case에 사용하는 데이터는 상수만 가능함
    > break가 없으면 break를 만날때까지 모든 구문을 전부 수행

    2) 기본 코드 예제

    #하나의 정수를 입력 받아서 1이면 중식 2이면 한식 3이면 분식 나머지는 다이어트로 출력
    import java.util.Scanner;
    public class SwitchMenu {
        public static void main(String[] args) {
            try(Scanner sc = new Scanner(System.in)){
                final int CHINA = 1;
                System.out.print("메뉴 선택 (1~3) : ");
                int menu = sc.nextInt();
                switch (menu){
                    case CHINA:
                        System.out.println("중식");
                        break;
                    case 2:
                        System.out.println("한식");
                        break;
                    case 3:
                        System.out.println("분식");
                        break;
                    default:
                        System.out.println("다이어트");
                        break;
                }
            }catch (Exception e){
                System.out.println(e.getLocalizedMessage());
            }
        }
    }

    5. while

    1) 기본구조

    while(boolean 표현식){
    	boolean 표현식이 false가 아니면 수행할 내용
    }
    > boolean 표현식이 false가 될 때 까지 내용을 반복

    2) 기본 코드 예제

    #1부터 10까지 합계
    public class WhileExample {
        public static void main(String[] args) {
            int tot = 0;
            int i = 0;
            while (i <= 10) {
                //반복할 내용
                tot = tot + i;
                i += 1; // i = i + 1;
            }
            System.out.println("합계 : " + tot);
        }
    }​

    6. do ~ while

    1) 기본 형식

    do{
    	boolean 표현식이 false가 아니면 수행할 내용
    }while(boolean 표현식);
    > boolean 표현식이 false가 될 때 까지 내용을 반복
    > "무조건 한 번은 수행한다 " 라는 의미를 전달할 목적으로 이용

    2) 기본 코드 예제

    #1부터 10까지 합계
    public class WhileExample {
        public static void main(String[] args) {
            int tot = 0;
            int i = 0;
            do {
                //반복할 내용
                tot = tot + i;
                i += 1; // i = i + 1;
            }while (i <= 10);
            System.out.println("합계 : " + tot);
        }
    }​

    7. for

    1) 기본형식

    for(초기식; boolean 표현식; 두번째부터 수행할 내용){
    	boolean 표현식이 false가 아닌 경우 수행할 내용
    }
    > 각 식은 생략 가능
    > 각 식에는 2개 이상의 문장을 사용해도 됨
    이 경우에는 ,로 구분

    # 기본 코드 예제
    public class WhileExample {
        public static void main(String[] args) {
            for(int i=0, j=0; i<10 && j<5; i++, j+=2){
                System.out.println(i);
                System.out.println(j);
            }
        }
    }​

    2) 배열을 순회하면서 수행

    for(임시변수 : 배열){
    	배열의 데이터를 임시변수에 하나씩 대입하면서 수행할 내용
    }
    #배열 순회 예제
    public class WhileExample {
        public static void main(String[] args) {
            for(int i=0, j=0; i<10 && j<5; i++, j+=2){
                System.out.println(i);
                System.out.println(j);
            }
            String [] names = {"KAKAO", "NAVER", "APPLE"};
            for(String name:names){
                System.out.println(name);
            }
        }
    }​

    8. 제어문 사용

    > 실행할 내용이 한 줄이면 { } 생략가능 
    > ( ) 다음에 ;을 하게 되면 제어문은 사용하지 않은 형태가 됨
    > 제어문은 별도의 블럭을 생성하는데 이전 블럭에 만든 것을 다시 만들 수는 없고 자신의 블럭 안에 만든 것은 자신의 블럭에서만 사용가능하고 제어문이 종료되면 블럭은 소멸됨
    > switch 의 case 에서 변수를 만드는 것은 수행될지 안될지 알 수 없기 때문에 안됨

    9. break 와 continue

    > 반복문 안에서 사용되면 if 와 함께 사용 됨

    1) break

    > switch 와 반복문 안에서 switch 와 반복문을 종료하는 기능
    > break 다음에 수행할 내용이 없다면 break 대신에 자신을 호출한 메서드에게 제어권을 넘기는 return으로 작성해도 됨

    2) continue

    > 반복문 안에서 더 이상 아래로 내려가지 않고 다음 반복으로 넘어가는 기능

    10. 무한 반복 만들기

    //1
    while(true){무한 반복}
    //2
    do{무한 반복}while(true);
    //3
    for(;;){무한 반복}

    11. 반복문에 레이블 사용

    레이블:반복문{}
    > break 나 continue 를 할 때 뒤에 레이블을 붙일 수 있음
    > 반복문 안에 반복문이 있을 때 바깥쪽 반복문을 종료하거나 넘어가고자 할 때 사용

    Array(배열)

    1. Array

    > 동일한 자료형으로 구성된 데이터의 연속적인 모임
    > 자바에서의 Array는 정적임
    한 번 만들어지면 내부 요소의 수정은 가능하지만 크기 변경은 안됨
    > 생성을 하면 데이터는 Heap에 생성이 됨
    > 동일한 용도로 사용되는 데이터는 이름이 하나인게 관리하기 편리하기 때문임
    여러 개의 데이터를 반복문이나 iterator를 이용해서 쉽게 사용할 수 있음
    > 배열은 하나의 public 속성을 갖는데 속성은 length
    배열이름.length 를 호출하면 한 단계 아래 하위 데이터의 개수를 리턴함
    length 속성은 읽기 전용

    2. 배열의 생성

    1) 초기 데이터를 가지고 생성

    • 선언할 때 만 가능
    배열 요소 1개의 자료형 [] 배열이름 ={데이터 나열...}

    2) 크기만 설정

    배열 요소 1개의 자료형 [] 배열이름 = new 배열 요소 1개의 자료형[개수];
    > 개수 만큼의 저장 공간이 확보되고 자동 초기화를 수행
    숫자의 경우는 0
    boolean의 경우는 false
    나머지는 null

    > 다시 선언하는 것도 가능
    배열이름 = new 배열요소 1개의 자료형[개수];

    3) [] 는 배열 이름 뒤에 기재해도 됨

    > 자바에서는 대부분 앞에 기재
    > 자료형[ ] : 배열

    3. 배열의 요소 접근

    배열이름[인덱스] : 인덱스는 0부터 length -1 까지

    4. 배열의 순회

    1) 기본 구조

    for(임시변수 : 배열이름){
    	배열의 데이터를 순차적으로 하나씩 임시변수에 대입하고 수행
    }

    2) 기본 예시 코드

    public class WhileExample {
        public static void main(String[] args) {
            //데이터를 가지고 배열 생성
            String [] worldCup = {"아르헨티나", "프랑스", "크로아티아", "모로코"};
            //배열의 데이터 순회
            int len = worldCup.length;
            for(int i=0; i<len; i=i+1){
                String imsi = worldCup[i];
                System.out.println(imsi);
            }
    
            //생성하고 데이터를 대입
            int [] ar = new int[3]; //숫자는 0으로 초기화
            ar[0] = 20;
            ar[1] = 30;
            //배열의 순회
            for(int temp : ar) {
                System.out.printf("%5d", temp);
            }
        }
    }

    5. 배열 사용 시 많이 발생하는 예외

    > NullPointerException : 배열의 메모리 할당이 이루어지지 않은 상태
    > ArrayIndexOutOfBoundsException : 인덱스 오류

    6. 다차원 배열

    > 배열의 배열
    > 배열 안의 요소가 배열인 형태
    > [ ]의 개수를 차원의 개수라고 함
    > 2차원 배열을 matrix 라고 함
    3차원 배열이나 4차원 배열을 사용하는 경우가 있는데 머신러닝에서 주로 이용

    1) 생성

    >초기 데이터를 가지고 생성
    자료형 [] [] 배열이름 = {{데이터 나열}, {데이터나열}, ... }

    > 각 행의 열 숫자가 동일한 경우
    자료형 [] [] 배열이름 = new 자료형 [크기][크기];

    > 열의 숫자를 다르게 생성
    자료형 [][] 배열이름 = new 자료형 [크기][];
    배열이름[0] = new 자료형[크기];

    2) 2차원 배열 사용

    배열이름[행인덱스][열인덱스] 하면 데이터에 접근
    배열이름[행인덱스]는 배열

    3) 2차원 배열에서의 length

    배열이름.length : 행의 개수
    배열이름[행인덱스].length : 열의 개수

    4) 배열은 만들 때 마지막을 가리키기 위해서 메모리를 사용하므로 메모리를 아끼고자 할 때는 2차원 배열을 1차원 배열로 만드는 것도 생각을 해봐야 함

    public class WhileExample {
        public static void main(String[] args) {
            //2차원 배열
            String [][] programmers = {
                    {"데니스", "비야네", "아르메스"},
                    {"로이스", "제임스", "토마스"}
            };
            System.out.println(programmers.length); //행의 개수 : 2EA
            System.out.println(programmers[0].length); //열의 개수 : 3EA
    
            for(String [] ar : programmers){
                for (String designer : ar){
                    System.out.print(designer + "\t");
                }
                System.out.println();
            }
            String [] langugeDesigner = {
                    "데니스", "비야네", "아르메스", "로이스", "제임스", "토마스"
            };
            for(int i=0; i< langugeDesigner.length; i++){
                System.out.print(langugeDesigner[i] + "\t");
                if(i % 3 ==2){
                    System.out.println();
                }
            }
        }
    }

    7. 배열에 데이터 추가

    > 배열은 크기 변경이 불가
    > 배열의 크기를 변경하고자 할 때는 배열의 데이터를 복사해서 수행해야 함
    > 배열을 복사하는 방법은 직접 알고리즘을 구현해도 되고 Arrays 클래스의 static 메서드인 Arrays.copy를 이용할 수 있음
    복사할 배열과 개수를 매개변수로 대입하면 됨

    8. 배열의 데이터를 하나의 문자열로 만들기

    > 배열은 toString 메서드가 없어서 문자열로 만들고자 하는 경우에는 Arrays.toString 메서드에 매개변수로 대입해서 결과를 리턴 받아야 함
    Arrays.toString은 배열 안의 모든 요소의 toString을 호출해서 결합함
    import java.lang.reflect.Array;
    import java.util.Arrays;
    
    public class WhileExample {
        public static void main(String[] args) {
            String [] ar = {"찰스 올라프", "버클리 올라프", "배네딧 올라프"};
            //위의 배열의 내용을 가지고 데이터를 1개 추가한 배열을 생성
            String [] br = new String[ar.length +1];
            //배열의 요소 복제
            for(int i=0; i<ar.length; i++){
                br[i] = ar[i];
            }
    
            String [] cr = Arrays.copyOf(ar, ar.length +1);
            cr[3] = "에브리타임 올라프";
            //배열의 요소들을 하나의 문자열로 생성
            System.out.println(Arrays.toString(cr));
        }
    }​

    9. Sorting

    > 배열은 데이터가 여러 개 이므로 접근을 할 때 원하는 순서대로 접근할 수 있도록 정렬을 하는 경우가 많음
    > 직접 알고리즘을 구현해서 할 수 있고 Arrays 클래스가 제공하는 sort 라는 메서드를 이용하는 방법이 있음
    대부분 API가 제공하는 메서드들은 Quick Sort 나 Heap 또는 Merge Sort 를 주로 이용
    선택 정렬이나 버블 정렬은 학습 단계에서 반복문을 공부할 목적으로 주로 하고 애플리케이션에서는 성능이 떨어지기 때문에 잘 사용하지 않음
    > Arrays.sort 메서드는 기본적으로 크기 비교가 가능한 메서드를 소유하고 있어야 하고 이를 직접 구현해서도 가능
    기본은 오름차순임

    1) Arrays.sort 메서드를 이용한 데이터의 정렬

    > 숫자 데이터와 문자열 그리고 Date 클래스의 배열은 별도로 메서드를 구현하지 않아도 오름차순 정렬이 가능
    > Wrapper 클래스 와 String 그리고 Date 는 Comparable 이라는 인터페이스가 구현되어 있기 때문임
    //문자열을 오름차순 정렬
    Arrays.sort(cr);
    System.out.println(Arrays.toString(cr));

    2) 선택 정렬(Selection Sort)

    첫 번째 데이터 부터 마지막 바로 앞 데이터까지 자신의 뒤에 있는 모든 데이터와 비교해서 정렬해나가는 방식

    앞의 데이터가 클 때 데이터를 교환하면 오름차순 정렬이 되고 뒤의 데이터가 클 떄 데이터를 교환하면 내림차순 정렬이 됨
    import java.util.Arrays;
    public class WhileExample {
        public static void main(String[] args) {
            int [] ar = {1, 5, 3, 2, 4};
            //선택 정렬
            for(int i=0; i<ar.length-1; i++){
                //기준의 뒤부터 마지막 자리까지
                for(int j=i+1; j<ar.length; j++){
                    //자리의 데이터를 비교해서 기준 자리의 데이터가 크면
                    //2개의 데이터를 swap
                    if(ar[i]>ar[j]){
                        int temp = ar[i];
                        ar[i] = ar[j];
                        ar[j] = temp;
                    }
                }
                //하나의 pass가 완료되면 출력
                System.out.println("[" + i + "번째 pass]" +Arrays.toString(ar));
            }
            System.out.println(Arrays.toString(ar));
        }
    }​

    10. search(검색)

    1) 검색 알고리즘

    > 순차 검색 : 데이터를 정렬하지 않은 상태에서 처음부터 끝까지 데이터를 찾을 때까지 비교해 나가는 방식
    > 제어 검색 : 데이터를 정렬한 상태에서 검색

    #binary search
    > 중앙에 있는 데이터와 비교해서 같으면 찾은 것이고 작으면 왼쪽 부분의 배열에 다시 다시 중앙 값과 비교하고 크면 오른 쪽의 배열에서 중앙값과 비교하면서 찾는 방식

    #fibonacci search
    > 피보나치 수열의 순서대로 검색해나가는 방식
    💡 fibonacci 수열 : 첫번째와 두번째는 1이고 세번째 부터는 앞의 2개 항의 합인 수열 (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... )

    #interpolation search
    > 찾는 위치를 계산해서 찾는 방식
    ( ( 검색값 - 최소값 ) / ( 최대값 - 최소값 ) ) * ( 최대인덱스 - 최소인덱스 ) + 1
    을 해서 찾는 위치를 결정하는 방식
    > 데이터의 간격이 균등할때 효과적임

    #tree search
    > 데이터를 저장할 때 tree 구조로 저장해서 검색에 활용

    #block search
    > 블록끼리는 정렬이 되어 있고 블럭 내부는 정렬이 되지 않은 경우 사용

    #hashing
    > 데이터에 key를 생성해서 찾아가는 방식으로 가장 빠르지만 메모리 효율은 떨어짐

     

Designed by Tistory.