2023.07.25 - java 문법 종합반(2주차)

mjjin·2023년 7월 24일
0

Java 문법 종합반

목록 보기
2/8

1. 연산자(Operator)

연산에 사용되는 표시나 기호를 연산자(operator)라고 한다.
연산에는 연산자와 피연산자가 있어야 하며
피연산자는 연산의 대상을 뜻한다.

<연산자의 종류>

  • 산술연산자 : +, -, *, /, %(나머지), <<, >>
  • 비교연산자 : >, <, >=, <=, ==, !=
  • 논리연산자 : &&(AND), ||(OR), !(NOT)
  • 대입연산자 : =, ++(+=), --(-=), *= 등
  • 기타연산자 : (type), ? :, instance of
    • ? : (삼항연산자) : 비교 연산자와 함께 쓰인다. 조건 ? 참 : 거짓 으로 작성
      ex) boolean b = (x == y) ? true : false;, String s = (x != y) ? "정답" : "오답)
    • instance of : 피 연산자가 조건에 명시된 클래스의 객체인지 비교
  • 비트연산자 : 연산중에서 제일 빠르며 Bit의 자리수를 옮기는 연산이다.

<연산자 우선순위>

연산자는 산술 > 비교 > 논리 > 대입 순으로 응답값이 결정된다.
단, 괄호로 감싸주면 괄호안의 연산이 최우선순위로 계산된다.
ex) x = 2, y = 9, z = 10일 때 result = x + 10 < y && y < z; 의 값은 false이다.


기타 연산자외에는 기존 Python에서 공부했던 내용이라 편안한 마음으로 강의를 들었다.
단, Python과 달리 Java에서는 몫만 출력된다는 차이점이 있었다.
예를 들어, 5/2를 출력 했을 때의 결과값은 2.5가 아닌 2가 나온다.
2.5를 출력하려면 5.0/2.0으로 나누면 나온다.

기타연산자 중에서는 삼항연산자가 조금 낯설었지만 작성법이 쉬워 금방 익힐 수 있을 것 같다.
비트 연산은 속도가 빠르다고는 하지만, 솔직히 저게 어떤 용도로 쓰이는지 모르겠다. 내가 쓸 일이 있을까..?
그냥 일단 가볍게 훑어만 봤고, 나중에 필요하면 검색하거나 따로 공부하는걸로 하자!

2. 조건문

특정 조건에 따라 다른 연산을 수행하고자 할 때 사용한다.

<if문>

if(조건1) {
    조건 1true일때 실행
} else if(조건2) {
    조건 2true일 때 실행
} else {
    조건1과 조건2false일 때 실행
}

<switch문>

switch (입력 변수){
case 입력값1 : 실행 구문
break;
case 입력값2 : 실행 구문
break;
case 입력값3 : 실행 구문
break;
default: 기본 실행 구문
break;
}
  • break는 생략가능

살 것 같다. 조건문이 나를 살렸다. 
조금 쉬어가는(?) 느낌으로 들을 수 있었다.
Objects.equals(좌,우)는 두 개의 값을 비교하는 메서드라고 한다.
나중에 메서드들만 따로 정리해둘 필요가 있을 것 같다.

3. 반복문

특정 조건에 따라 연산을 반복수행 할 때 사용한다.
반복문 작성시 주의해야 할 점은 무한루프에 빠지지 않도록 조심해야 한다.

<for문>

for (초기값; 조건문; 증감식) {
	조건문이 true일 때 반복수행
}
  • 초기값 : 반복문에 사용될 변수를 초기화하며 처음에 한 번만 수행된다. ex) int i=0
  • 조건문 : 조건문이 true인 경우 반복문이 진행된다. ex) i < 7
  • 증감식 : 반복문을 제어하기 위해 사용한다. ex) i++

코드의 실행순서
초기값 -> 조건문 -> 코드 수행 -> 증감식 -> 조건문 -> 코드 수행 -> 증감식 -> 조건문..(반복)

+ 향상된 for문

for (변수정의: 배열명) {
	배열의 길이만큼 반복
}

향상된 for문은 배열을 갖고 반복작업을 할 때 주로 사용된다.
기존 for문에 비해 코드가 간결해질 수 있다는 장점이 있지만
배열만 사용 가능하며 배열값을 직접 바꿀수 없다는 단점이 있다.

기존 for문에서 배열을 사용하지 못하는 것은 아니며
컨벤션에 따라 일반적인 for문만 사용하는 곳도 있기 때문에
기존for문이 익숙하지 않다면 옵션정도로만 알아두고 가도 괜찮다.

<while문>

초기값 //ex) int number = 0;
while(조건문) { //조건문 ex)number < 3 
    증감식 // ex) number++;
    조건문이 true인 동안 반복수행
}

코드에 따라 초기값과 증감식을 작성하지 않아도 반복이 가능하지만 ex)while(true) {}
사용하지 않게 될 때에는 무한루프에 빠질 수 있기에 꼭 유의하여 작성이 필요하다.

<do-while문>

do {
    처음 실행시 무조건 실행
    이후부터는 조건문이 true인 동안 실행
} while (조건문);

기존의 while문과 다른 점은,
첫 실행시 무조건 코드를 한번 실행 후 while의 조건문에 따라 반복을 실행한다.

<Break/Continue>

  • break : 가장 가까운 블록의 for문,while,swich문을 중단한다. (stop)
  • continue : 가장 가까운 반복부분을 탈출 후 다음 반복으로 넘어간다. (pass)
//사용 예제
while(true){
    코드1
    if(조건1){
    	조건코드1
        break;
    } else if (조건2) {
    	조건코드2
        continue;
    }
    코드2
}
코드3

조건1이 true일 때의 코드 동작 : 코드1 -> 조건코드1-> 코드3
조건2가 true일 때의 코드 동작 : 코드1 -> 조건코드2 -> 코드1 -> 코드2 ... (반복문종료시 코드3)


for 반복문의 경우, 배열을 사용했던 경우가 많았기 때문에
작성 방식이 조금 낯설었지만 실제 여러 번 코드를 작성해보니 적응이 된 것 같다!

4. 배열(Array)

여러개의 변수를 저장할 때 사용하는 변수로
배열의 변수를 선언할 때에는 일반적으로 변수타입[] 변수명으로 선언하며
선언한 타입과 다른 타입의 변수는 배열에 저장 할 수 없다.

선언 방식

1. 타입[] 배열이름;
2. 타입 배열이름[];

생성 방식

new 타입[배열길이];

선언과 생성을 동시에 진행할 때

1. 타입[] 배열이름 = new 타입[배열길이];
2. 타입[] 배열이름 = {배열요소1, 배열요소2,};
3. 타입[] 배열이름 = new 타입[]{배열요소1, 배열요소2,};

배열 요소의 조회 방법
배열[index]로 배열의 요소를 조회할 수 있다.
ex) array[0] = array배열의 0번째 인덱스

<복사>

배열은 참조형 변수로, 실제 값이 아닌 주소값을 가지게 된다.

- 얕은 복사

int[] a = { 1, 2, 3, 4 };
int[] b = a; // 얕은 복사

b[0] = 3; // b 배열의 0번째 순번값을 3으로 수정했습니다. (1 -> 3)

System.out.println(a[0]); // 출력 3  <- a 배열의 0번째 순번값도 3으로 조회됩니다. 

대입연산자로 복사하게 될 시 b를 수정하면, a도 함께 수정된다. (a수정시에도 b가 수정된다.)
결국 배열 b와 배열 a는 변수명만 다를 뿐, 원본 값은 같다.
배열 a와 배열 b가 독립적인 값을 가지게 하려면 깊은 복사로 복사해야한다.

- 깊은 복사

깊은 복사를 하는 방법에 대해서는 여러가지 방법이 있다.

  • 반복문을 통해 배열요소를 하나하나 꺼내 새로운 배열에 저장하는 방법

    int[] a = { 1, 2, 3, 4 };
    int[] b = new int[a.length]; 
    
    for (int i = 0; i < a.length; i++) {
      b[i] = a[i]; 
    }
    
  • clone() 메서드를 이용해 복사하는 방법

    int[] a = { 1, 2, 3, 4 };
    int[] b = a.clone();

    clone() 메서드는 가장 쉽게 복사할 수 있지만, 다차원 배열에서는 얕은 복사로 동작하기 때문에
    사용시 주의가 필요하다.

  • Arrays.copyOf() 메서드를 이용해 복사하는 방법

    int[] a = { 1, 2, 3, 4 };
    int[] b = Arrays.copyOf(a, a.length);

    clone() 메서드의 단점을 해결 할 수 있지만 clone 메서드보다는 조금 귀찮다.
    파라미터로는 배열, 배열의 길이가 들어가게된다.

<String 배열>

배열중에서도 가장 많이 사용하는 배열이다.

  • 자주 사용되는 메서드

    메서드응답값 타입설명
    length()int문자열의 길이를 반환한다.
    charAt(int index)char문자열에서 해당 index의 문자를 반환한다.
    substring(int from, int to)String문자열에서 해당 범위(from~to)에 있는 문자열을 반환한다. (to는 범위에 포함되지 않음)
    equals(String str)boolean문자열의 내용이 같은지 확인한다. 같으면 결과는 true, 다르면 false가 된다.
    toCharArray()char[]문자열을 문자배열(char[])로 변환해서 반환한다.
    new String(char[] charArr)String문자배열(char[]) 을 받아서 String으로 복사해서 반환한다.
  • 메서드 사용 예시

    String str = "ABCD";
    
    //(1) length
    int strLength = str.length();
    System.out.println(strLength); //출력값 : 4
    
    //(2) charAt(int index)
    char strChar = str.charAt(2);
    System.out.println(strChar); //출력값 : C
    
    //(3) substring(int fromIdx, int toIdx)
    String strSub = str.substring(0, 3);
    System.out.println(strSub); //출력값 : ABC
    
    //(4) equals(String str)
    String newStr = "ABCD";
    boolean strEqual = newStr.equals(str);
    System.out.println(strEqual); //출력값 true
    
    //(5) toCharArray() : String -> char[]
    char[] strCharArray = str.toCharArray();
    System.out.println(strCharArray[1]); //출력값 B
    
    //(6) char[] -> String -> char
    char[] charArray = {'A', 'B', 'C'};
    String charArrayString = new String(charArray);
    System.out.println(charArrayString);  //출력값 ABC

<다차원 배열>

2차원 이상의 배열로, 배열 요소로 또 다른 배열을 가진다.

선언 방식

1. 타입[][] 배열이름;
2. 타입 배열이름[][];
3. 타입[] 배열이름[];

생성 방식

타입 배열이름[행의길이][열의길이] = {

    {배열요소[0][0], 배열요소[0][1],},

    {배열요소[1][0], 배열요소[1][1],},

    {배열요소[2][0], 배열요소[2][1],},};

- 가변배열

배열의 마지막 차수의 길이를 지정하지 않고, 가변적으로 생성이 가능하다.

가변배열 예시)

int[][] array = new int[3][];

array[0] = new int[2];
array[1] = new int[4];
array[2] = new int[1];
int[][] array2 = {
	{10, 20},
    {10, 20, 30, 40},
    {10}
}

5. 컬렉션

배열보다 다수의 참조형 데이터를 더 쉽고 효과적으로 처리할 수 있다.
컬렉션의 종류로는 List, Set, Queue, Map 등이 있다.

  • List : 순서가 정해진 데이터의 집합
  • Queue : 컴퓨터 버퍼에서 주로 사용, 먼저 들어간 자료가 먼저 나오는 구조(FIFO)
    • FIFO : First In First Out의 약자
  • Set : 중복되지 않는 데이터의 집합, 순서 X
  • Map : (Key, Value)의 쌍으로 이루어진 집합, 순서 X

<List>

ArrayList<Integer> intList = new ArrayList<Integer>();

  • 기능

    • 선언 : ArrayList<Integer> intList 형태로 선언
    • 생성 : new ArrayList<Integer>();
    • 초기화 : 불필요
    • 값 추가 : intList.add({추가할 값})
    • 값 수정 : intList.set({수정할 순번},{수정할 값})
    • 값 삭제 : intList.remove({삭제할 순번})
    • 전체출력 : intList.toStriong()
    • 전체제거 : intList.clear()
  • 예시 코드

    //선언 + 생성
    ArrayList<Integer> intList = new ArrayList<Integer>();
    
    //추가
    intList.add(99); //값 추가
    intList.add(22);
    intList.add(35);
    System.out.println(intList.get(0)); //출력 : 99
    
    
    //수정
    intList.set(2, 30); //2번째 값의 Idx를 30으로 수정
    System.out.println(intList.get(1)); //출력 : 30
    
    //삭제
    intList.remove(0); //0번째 Idx를 삭제
    System.out.println(intList.get(0)); //출력 : 22
    
    //전체삭제
    System.out.println(intList.toString());//출력 : [22, 30]
    intList.clear();
    System.out.println(intList.toString()); //출력 : []
    

-LinkedList

LinkedList<Integer> linkedList = new LinkedList<Integer>();

기본적인 기능은 ArrayList와 동일하지만 차이점으로는 크게 두 가지가 있다.

  • 장점 : 중간에 값을 추가하는 기능

  • 단점 : 값을 나누어 담기 때문에 모든 값을 조회할 때에는 속도가 느림

  • 기능

    • 중간에 값 추가 : linkedList.add({추가할 순번}, {추가할 값})

그 외의 기능은 ArrayList와 동일한 방식으로 사용한다.

-Stack

수직으로 값을 쌓아놓고, 넣었다가 뺀다.
Stack<Integer> intStack = new Stack<Integer>();

최근 저장된 데이터를 나열하고 싶거나, 데이터의 중복 처리를 막고 싶을 때 사용한다.

  • 기능

    • 선언 : Stack<Integer> intStack
    • 생성 : new Stack<Integer>();
    • 추가 : intStack.push({추가할 값})
    • 조회 : intStack.peek() //맨 위의 값 출력
    • 꺼내기 : intStack.pop() // 맨 위의 값을 꺼냄. (삭제)
  • 예시코드

    //선언 및 생성
    Stack<Integer> intStack = new Stack<>();
    
    //값 추가
    intStack.push(10);
    intStack.push(15);
    intStack.push(1);
    
    //조회 peek는 값이 사라지지 않는다.
    System.out.println(intStack.peek()); //출력 : 1
    
    //크기 구하기
    System.out.println(intStack.size()); //출력 : 3
    
    
    // 값이 없어질 때 까지 출력
    while(!intStack.isEmpty()) {
        //pop은 꺼내는 순간 값이 사라진다.
        System.out.println(intStack.pop()); //출력 : 1, 15, 10
    }

<Queue>

생성자가 없는 인터페이스로 LinkedList를 사용한다.
Queue<Integer> intQueue = new LinkedList<>();

  • 기능

    • 선언 : Queue<Integer> intQueue
    • 생성 : new LinkedList<Integer>();
    • 추가 : intQueue.add({추가할 값})
    • 조회 : intQueue.peek()
    • 꺼내기 : intQueue.poll()
  • 예시코드

    //선언 및 생성
    Queue<Integer> intQueue = new LinkedList<>();
    
    intQueue.add(1);
    intQueue.add(5);
    intQueue.add(9);
    
    // peak와 size
    System.out.println(intQueue.peek()); //출력 : 1
    System.out.println(intQueue.size()); //출력 : 3
    
    //값이 없어질 때 까지 출력
    while(!intQueue.isEmpty()) {
        System.out.println(intQueue.poll()); //출력 : 1, 5, 9
    }
    

<Set>

순서가 없고 중복이 없으며 생성자가 없는 인터페이스
Set<Integer> intSet = new HashSet<>();

HashSet, TreeSet 등으로 응용해서 같이 사용이 가능하다.

  • 기능

    • 선언 : Set<Integer> intSet
    • 생성 : new HashSet<Integer>();
    • 추가 : intSet.add({추가할 값})
    • 삭제 : intSet.remove({삭제할 값})
    • 포함확인 : intSet.contains({포함확인 할 값})
  • 예시코드

    //선언 및 생성
    Set<Integer> intSet = new HashSet<>();
    
    //값 추가
    intSet.add(1);
    intSet.add(12);
    intSet.add(15);
    intSet.add(9);
    intSet.add(12);
    
    //전체 출력
    for (Integer value: intSet) {
        System.out.println(value); //출력 : 1, 9, 12, 15 (중복값은 출력되지 않음)
    }
    
    //contains 포함여부 확인
    System.out.println(intSet.contains(2)); //출력 : false
    System.out.println(intSet.contains(12)); //출력 : true
    
    //삭제
    intSet.remove(1);
    System.out.println(intSet); //출력 : 9, 12, 15

<Map>

Key, Value 값을 가지며 Key는 중복되지 않는다.

Python의 Dicionary 구조와 비슷하다.

  • 예시코드
  //선언 및 생성
  Map<String, Integer> intMap = new HashMap<>();

  //추가
  intMap.put("가", 1);
  intMap.put("나", 1);
  intMap.put("다", 1);
  intMap.put("라", 13);
  intMap.put("마", 1);
  intMap.put("가", 1);

  // key 값 전체 출력
  for (String key : intMap.keySet()) {
      System.out.println(key);  //출력값 : 가,나,다,라,마,라 (key는 중복값 허용X)
  }

  //value 값 전체 출력
  for (Integer value : intMap.values()) {
      System.out.println(value); //출력값 : 1,1,1,1,13 (Value는 중복값 허용)
  }

  System.out.println(intMap.get("라")); //출력값 : 13

6. 2주차 숙제

자료구조 요리 레시피 메모장 만들기

<문제내용>

  • 입력값

    • 저장할 자료구조명을 입력합니다. (List / Set / Map)
    • 내가 좋아하는 요리 제목을 먼저 입력합니다.
    • 이어서 내가 좋아하는 요리 레시피를 한문장씩 입력합니다.
    • 입력을 마쳤으면 마지막에 “끝” 문자를 입력합니다.
  • 출력값

    • 입력이 종료되면 저장한 자료구조 이름과 요리 제목을 괄호로 감싸서 먼저 출력 해줍니다.
    • 이어서, 입력한 모든 문장앞에 번호를 붙여서 입력 순서에 맞게 모두 출력 해줍니다.

    ex) 입력 예시

    Set
    백종원 돼지고기 김치찌개 만들기
    돼지고기는 핏물을 빼주세요.
    잘익은 김치 한포기를 꺼내서 잘라주세요.
    냄비에 들기름 적당히 두르고 김치를 넣고 볶아주세요.
    다진마늘 한스푼, 설탕 한스푼 넣어주세요.
    종이컵으로 물 8컵 부어서 센불에 끓여주세요.
    핏물 뺀 돼지고기를 넣어주세요.
    된장 반스푼, 양파 반개, 청양고추 한개를 썰어서 넣어주세요.
    간장 두스푼반, 새우젓 두스푼, 고춧가루 두스푼반 넣어주세요.
    중불로 줄여서 오래 끓여주세요~!!	
    마지막에 파 쏭쏭 썰어서 마무리하면 돼요^^
    끝  

    ex) 예시 출력

    [ Set 으로 저장된 백종원 돼지고기 김치찌개 만들기 ]
    1. 돼지고기는 핏물을 빼주세요.
    2. 잘익은 김치 한포기를 꺼내서 잘라주세요.
    3. 냄비에 들기름 적당히 두르고 김치를 넣고 볶아주세요.
    4. 다진마늘 한스푼, 설탕 한스푼 넣어주세요.
    5. 종이컵으로 물 8컵 부어서 센불에 끓여주세요.
    6. 핏물 뺀 돼지고기를 넣어주세요.
    7. 된장 반스푼, 양파 반개, 청양고추 한개를 썰어서 넣어주세요.
    8. 간장 두스푼반, 새우젓 두스푼, 고춧가루 두스푼반 넣어주세요.
    9. 중불로 줄여서 오래 끓여주세요~!!	
    10. 마지막에 파 쏭쏭 썰어서 마무리하면 돼요^^  

<코드작성>

import java.util.*;

public class Quest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        //type별 변수 생성
        ArrayList<String> inputStr = new ArrayList<>();
        LinkedHashSet<String> inputSet = new LinkedHashSet<>();
        Map<Integer, String> inputMap = new HashMap<>();

        //데이터 타입과 제목
        String dataType = sc.nextLine();
        String title = sc.nextLine();


        if (Objects.equals(dataType, "List")) {

            //List 타입 저장
            while(true) {
                String input = sc.nextLine();
                if (Objects.equals(input, "끝")) {
                    break;
                }
                inputStr.add(input);
            }
            System.out.printf("[ %s %s ]%n",dataType,title);
            //List 타입 반목문 출력
            for (int i = 1; i <= inputStr.size(); i++) {
                System.out.println(i + ". " + inputStr.get(i-1));
            }

        } else if (Objects.equals(dataType, "Set")) {
            while(true) {
                String input = sc.nextLine();
                if (Objects.equals(input, "끝")) {
                    break;
                }
                inputSet.add(input);
                }
            //힌트부분의 code//
            Iterator iterator = inputSet.iterator();
            System.out.printf("[ %s %s ]%n",dataType,title);
            for (int i=0; i < inputSet.size(); i++) {
                System.out.println((i+1) + ". " + iterator.next());
            }
        } else if (Objects.equals(dataType, "Map")) {
            int i = 0;
            while(true) {
                String input = sc.nextLine();
                if (Objects.equals(input, "끝")) {
                    break;
                }
                i++;
                inputMap.put(i, input);
            }
            System.out.printf("[ %s %s ]%n",dataType,title);
            for (int k = 1; k <= inputMap.size(); k++) {
                System.out.println(k + ". "+inputMap.get(k));
            }
        } else {
            System.out.println("잘못된 입력값입니다.");
        }
    }
}

코드가 정말 난잡하다...!!
Set 부분에선 힌트의 도움을 받았지만
최대한 힌트 없이 혼자 힘으로 작성해보고자 노력한 결과물이다.
코드 정리는 조금 더 배운 뒤 생각해보기로 하고
우선 기능 구현과 배움에 집중하기로 했다.

<문제>

-Set 출력시 뒤죽박죽 출력.

  • 문제의 코드

    //
    Scanner sc = new Scanner(System.in);
    Set<String> inputSet = new HashSet<>();
    
      while(true) {
          String input = sc.nextLine();
          if (Objects.equals(input, "끝")) {
              break;
          }
          inputSet.add(input);
          }
      //힌트부분의 code//
      Iterator iterator = inputSet.iterator();
      System.out.printf("[ %s %s ]%n",dataType,title);
      for (int i=0; i < inputSet.size(); i++) {
          System.out.println((i+1) + ". " + iterator.next());
      }
      
    //입력 값
      Set
      제목
      과정 1
      과정 2
      과정 3
      과정 4
    //출력 값
    [ Set 제목 ]
    1. 과정 2
    2. 과정 1
    3. 과정 4
    4. 과정 3

    	정말 의외로 List와 Map은 문제 없이 잘 성공했다.
    	다만 Set에서 순서가 뒤죽박죽으로 출력되는 문제가 발생했다.
    	Set은 중복이 없고, 순서가 없는 것으로 알고 있는데
    	이걸 어떻게 해결해야 할 지 조금 고민이 된다.

<문제해결>

  • 코드수정전

    Set<String> inputSet = new HashSet<>();
  • 코드수정후

    LinkedHashSet<String> inputSet = new LinkedHashSet<>();

    HashSet외에도 Treeset / LinkedHashSet이 있다고 한다.

    • HashSet : 가장 빠르지만 순서를 전혀 예측할 수 없음
    • TreeSet : 정렬된 순서대로 보관하며 정렬 방법을 지정할 수 있음
    • LinkedHashSet : 추가된 순서 또는 가장 최근에 접근한 순서대로 접근 가능

HashSet을 사용했기 때문에 순서를 예측할 수 없는 결과값이 나왔던 것이었다.
LinkedHashSet으로 코드를 수정하자 거짓말처럼 순서대로 잘 출력되기 시작했다.
막연하게 Set은 순서가 없다고만 생각했는데,이번 기회에 좋은 배움이 되었다.

0개의 댓글