Skip to content

Latest commit

 

History

History
374 lines (286 loc) · 15.1 KB

제어문.md

File metadata and controls

374 lines (286 loc) · 15.1 KB

자바가 제공하는 제어문을 학습하세요

제어문: 프로그램의 흐름을 제어할 수 있도록 도와주는 실행문

  • Decision-Making Statements: if, if-else, switch
  • Looping Statements: for, while, do-while
  • Branching Statements: break, continue, return

Decision-Making Statements

의사결정을 할때 쓰인다. 어느 코드블럭을 실행해야 할지 선택해야 할때 쓰인다.

  1. if statement
  2. if-else statement
  3. switch statement

if statement

if (condition) { /* code */ }

condition이 true일 때 code블럭 실행

if-else statement

if (condition) { /* code1 */ }
else { /* code2 */ }

condition이 true이면 code1 실행, 아니면 code2 실행

switch statement

선택문이라 불린다. 변수variable나 식expression의 값이 다양한 분기mutli-branch를 통해 프로그램의 실행 흐름을 제어할 수 있게 해준다. 다양한 분기를 ifelse if보다 쉽게 만들 수 있으며, break 키워드를 이용해 각 분기를 마친다.

switch 문은 하나의 변수나 식에 담긴 값을 각 case 키워드로 선언된 값들과 비교해 둘이 일치하는 경우 그 case의 코드 블럭을 실행시킨다.

int var = 3;

switch (var) {
    case 1:
        System.out.println("one");
        break;
    case 2:
        System.out.println("two");
        break;
    case 3:
        System.out.println("three");
        break;
    case 4:
        System.out.println("four");
        break;
    default:
        System.out.println("others");
        break;
}
//>> three

switch문의 사용방식이 Java 12까지 사용되는 전통적인 방식의 switch문의 문법이다. Java 13부터는 전통적인 방식의 몇가지 문제점을 개선한 새로운 기능들이 추가되었다.

전통적인 방식의 문제점들

  1. Default fall through due to missing break
  2. Multiple values per case not supported
Default fall through due to missing break

break 키워드 쓰는 것을 잊었을 경우 그 아래있는 코드 블럭이 실행된다.

int itemCode = 1;
switch (itemCode) {
    case 001 :
        System.out.println("It's a laptop!");
        // missed out break here
    case 002 :
        System.out.println("It's a desktop!");
        break;
}

//>> It's a laptop!
//>> It's a desktop!
Multiple values per case not supported

하나의 case에는 하나의 값만 비교할 수 있다.

switch (itemCode) {
    case 001:
    case 002:
    case 003:
    System.out.println("It's an electronic gadget!");
}

개선된 switch문의 기능들

  1. Supports multiple values per case
  2. yield is used to return a value
  3. switch with arrows
  4. scope
Supports multiple values per case
switch (itemCode) {
    case 001, 002, 003 :
        System.out.println("It's an electronic gadget!");
        break;
    case 004, 005:
        System.out.println("It's a mechanical device!");
        break;
}
yield is used to return a value

Java 13부터는 yield라는 키워드를 통해 switch문이 값을 반환할 수 있게 되었다. 따라서 switch문을 식expression으로도 사용이 가능하게 되었다. 그리고 yield 키워드가 값을 반환하면서 switch문을 끝내기 때문에 break은 더이상 사용할 필요가 없어졌다.

int val = switch (code) {
    case "x", "y" :
        yield 1;
    case "z", "w" :
        yield 2;
}
switch with arrows

switch문과 함께 화살표 연산자(->)를 사용할 수 있다. 그리고 화살표 연산자의 우변에 올 수 있는 것은 다음과 같다.

  • Statement / expression
  • throw statement
  • {} block

화살표 연산자를 사용하게 되면서 break문을 사용할 필요가 없어졌다.

switch (itemCode) {
    case 001 -> System.out.println("It's a laptop!");
    case 002 -> System.out.println("It's a desktop!");
    case 003,004 -> System.out.println("It's a mobile phone!");
}
scope

Java 13부터 switch문의 각 case{}을 쓸 수 있게되어, case-level의 scope를 사용할 수 있게 되었다.

switch (errorCode) {
    case 101: {
        // This variable exists just in this {} block
        int num = 200;
        break;
    }
    case 300: {
        // This is ok, {} block has a separate scope
        int num = 300;
        break;
    }
}

ZetCode GeeksforGeeks

Looping Statements

while (expression) { statement; }
do { statement; } while (expression)
for (초기값; 조건; 방향&간격) { statement; }
for (<type> <instance>: <type-iterable>) { statement; }

Branching Statements

break statement

while, for 또는 switch문을 끝낼 수 있는 구문이다.

continue statement

loop문에서 continue문이 실행되면 그 아래 코드들은 스킵한 뒤에 다음 스텝의 루프를 실행한다.


Guide to Control Flow Statements in Java

과제

과제 0. JUnit 5 학습하세요

  • 인텔리J, 이클립스, VS Code에서 JUnit 5로 테스트 코드 작성하는 방법에 익숙해 질 것.
  • 이미 JUnit 알고 계신분들은 다른 것 아무거나!
  • 더 자바, 테스트 강의도 있으니 참고하세요~

과제 1. live-study 대시 보드를 만드는 코드를 작성하세요

  • 깃헙 이슈 1번부터 18번까지 댓글을 순회하며 댓글을 남긴 사용자를 체크 할 것.
  • 참여율을 계산하세요. 총 18회에 중에 몇 %를 참여했는지 소숫점 두자리가지 보여줄 것.
  • Github 자바 라이브러리를 사용하면 편리합니다.
  • 깃헙 API를 익명으로 호출하는데 제한이 있기 때문에 본인의 깃헙 프로젝트에 이슈를 만들고 - 테스트를 하시면 더 자주 테스트할 수 있습니다.

과제를 수행하기 위한 주요 클래스들

  • GitHubBuilder
    • withOAuthToken() 메소드에 Github에서 발급받은 personal token을 넘겨 Github 인스턴스를 반환받을 수 있다.
  • GitHub
    • getRepository() 메소드에 원하는 repository의 '<owner_login>/<repo_name>' 문자열을 넘겨 GHRepository 인스턴스를 반환받을 수 있다.
  • GHRepository
    • getIssues() 메소드에 GHIssueState.ALL과 같은 이슈의 상태값을 넘겨 해당 repository의 issue들을 필터링해서 List<GHIssue> 인스턴스로 반환받을 수 있다.
  • GHIssue
    • getComment() 메소드를 호출해 해당 GHIssue 인스턴스의 comment들을 List<GHIssueComment> 인스턴스로 반환받을 수 있다.
  • GHIssueComment
    • getUser() 메소드를 호출해 해당 GHIssueComment 인스턴스의 작성자 정보를 GHUser 인스턴스로 반환받을 수 있다.
  • GHUser
    • getLogin() 메소드를 호출해 해당 GHUser 인스턴스의 loginString 인스턴스로 반환받을 수 있다.

통계를 내기 위한 알고리즘

  1. 위 Github api의 클래스들을 활용해 각 댓글 작성자들이 어느 이슈에 댓글을 달았는지를 HashMap<String, Set<Integer>>의 인스턴스에 작성자의 login이슈 번호들의 집합을 생성
  2. 반복문을 통해 1.에서 만든 HashMap작성자를 키로 하는 value의 길이를 이슈 전체 길이로 나눠 작성자마다의 참여율 계산

Class for Github issue comments collecting

과제 2. LinkedList를 구현하세요

LinkedList

  • node(vertex)value과 다음 노드의 위치next를 가지는 객체
  • head LinkedList의 첫번째 node를 가리킨다.
  1. 각 node는 값value와 다음 노드로 연결되는 포인터(링크)next를 가진다.
  2. 노드의 종류는 head와 일반 원소가 되는 node가 있다.
  3. head는 값은 가지지 않으며 항상 LinkedList의 첫번째 node를 가리킨다.
  4. node는 다음 node가 없는 경우 null을 가리킨다.
정수를 저장하는 ListNode 클래스를 구현하세요
  • public ListNode(int value)
    1. ListNode 인스터스의 this.valuevalue값을 할당한다.
  • ListNode add(ListNode head, ListNode nodeToAdd, int position)를 구현하세요.
    1. LinkedList의 head 노드를 파라미터로 받기 때문에 static으로 선언한다.
    2. position-1 인덱스에 위치한 node의 next 프로퍼티를 nodeToAdd로 바꾼다.
    3. nodeToAddnext 프로퍼티를 position 인덱스에 위치한 node로 바꾼다.
    4. position이 양수가 아니거나 LinkedList의 길이+1을 초과하면 null을 반환한다.
  • ListNode remove(ListNode head, int positionToRemove)를 구현하세요.
    1. LinkedList의 head 노드를 파라미터로 받기 때문에 static으로 선언한다.
    2. positionToRemove-1 인덱스에 위치한 node의 next 프로퍼티를 positionToRemove 인덱스에 위치한 node의 next로 바꾼다.
    3. positionToRemove가 양수가 아니거나 LinkedList의 길이+1을 초과하면 null을 반환한다.
  • boolean contains(ListNode head, ListNode nodeTocheck)를 구현하세요.
    1. nodeToChecknull이면 return false
    2. 리스트의 각 노드의 주소값과 nodeToCheck의 주소값을 비교한다.
    3. 같은 게 있을 때 return true
    4. 리스트의 끝까지 같은게 없으면 return false

ListNode Implementation
ListNode Test

head를 프로퍼티로 가지는 LinkedList

ListNode에서 static으로 선언된 메소드들을 LinkedList라는 객체의 메소드로 만들어 ListNode head 파라미터를 생략해 보았다.


LinkedList Implementation
LinkedList Test

과제 3. Stack을 구현하세요

Stack

  • 길이가 동적인 컬렉션을 가진다.
  • 가장 최근 input의 indextop를 알고있다.
int 배열을 사용해서 정수를 저장하는 Stack을 구현하세요
  • public Stack()
    1. int 배열을 가지는 Stack이기에 int배열의 사이즈를 초기에 정한다.
    2. this.top의 값을 -1로 초기화한다.
  • void push(int data)를 구현하세요.
    1. 해당 사이즈를 초과하면 길이가 1이 더 늘어난 배열을 생성한다.
    2. 기존 스택의 값을 모두 복사한다.
    3. 새로운 값을 배열에 넣는다.
    4. this.top의 값을 1 증가 시킨다.
  • int pop()을 구현하세요.
    1. 길이가 0인 스택은 Exception을 던진다.
    2. 길이가 0이 아닌 스택은 배열의 this.top 인덱스에 위치한 값을 가져온다.
    3. this.top의 값을 1 감소 시킨 후 가져온 값을 반환한다.

Stack Implementation
Stack Test

과제 4. 앞서 만든 ListNode를 사용해서 Stack을 구현하세요

ListNode head를 가지고 있는 ListNodeStack 클래스를 구현하세요

  • public Stack()
    1. ListNodehead를 만든다.
  • void push(int data)를 구현하세요.
    1. datavalue로 가지는 ListNode 인스턴스를 만든다.
    2. 1.에서 만든 인스턴스를 첫번째 노드로 add한다.
  • int pop()을 구현하세요.
    1. 리스트의 길이가 0이면 Exception을 던진다.
    2. 리스트의 첫번째 노드의 value를 가져온다.
    3. 리스트의 head가 첫번째 노드의 next를 가리키게 한다.

ListNodeStack Implementation
ListNodeStack Test

(optional) 과제 5. Queue를 구현하세요

배열을 사용해서 한번

  • public Queue()
    1. int 배열을 가지는 Queue이기에 int배열의 사이즈를 초기에 정한다.
    2. this.last 값을 -1로 초기화하여 Queue의 마지막 인덱스를 초기화한다.
  • void add(int data)
    1. 해당 사이즈를 초과하면 길이가 1이 더 늘어난 배열을 생성한다.
    2. 기존 큐의 값을 모두 복사한다.
    3. 새로운 값을 배열에 넣는다.
    4. this.last의 값을 1증가 시킨다.
  • int remove()
    1. 비어있는 큐인지 확인하여 비어있으면 Exception을 던진다.
    2. 큐의 배열의 첫번째 값을 가져온다.
    3. 배열의 모든 값들의 위치를 (원래 인덱스-1) 위치로 옮긴다.
    4. this.last의 값을 1 감소 시킨 후 가져온 값을 반환한다.
  • int peek()
    1. 비어있는 큐인지 확인하여 비어있으면 Exception을 던진다.
    2. 큐의 배열의 첫번째 값을 반환한다.
  • boolean isEmpty()
    1. this.last 값이 -1이면 returne true
    2. 아니면 return false를 반환한다.

Queue Implementation
Queue Test

ListNode를 사용해서 한번

  • public ListNodeQueue()
    1. LinkedList의 head를 만든다.
    2. this.last 값을 0으로 초기화하여 Queue의 마지막 인덱스를 초기화한다.
  • void add(int data)
    1. datavalue로 가지는 ListNode 인스턴스를 만든다.
    2. this.last를 1 증가시킨다.
    3. 1.에서 만든 인스턴스를 this.last 인덱스에 위치한 노드로 add한다.
  • int remove()
    1. 비어있는 큐인지 확인하여 비어있으면 Exception을 던진다.
    2. this.last를 1 감소시킨다.
    3. LinkedList의 첫번째 노드를 remove하며 value를 반환한다.
  • int peek()
    1. 비어있는 큐인지 확인하여 비어있으면 Exception을 던진다.
    2. LinkedList의 첫번째 노드를 가져와 value를 반환한다.
  • boolean isEmpty()
    1. this.last 값이 0이면 returne true
    2. 아니면 return false를 반환한다.

ListNodeQueue Implementation
ListNodeQueue Test