제어문: 프로그램의 흐름을 제어할 수 있도록 도와주는 실행문
- Decision-Making Statements:
if
,if-else
,switch
- Looping Statements:
for
,while
,do-while
- Branching Statements:
break
,continue
,return
의사결정을 할때 쓰인다. 어느 코드블럭을 실행해야 할지 선택해야 할때 쓰인다.
if
statementif-else
statementswitch
statement
if (condition) { /* code */ }
condition이 true
일 때 code블럭 실행
if (condition) { /* code1 */ }
else { /* code2 */ }
condition이 true
이면 code1 실행, 아니면 code2 실행
선택문이라 불린다. 변수variable나 식expression의 값이 다양한 분기mutli-branch를 통해 프로그램의 실행 흐름을 제어할 수 있게 해준다. 다양한 분기를 if
나 else 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부터는 전통적인 방식의 몇가지 문제점을 개선한 새로운 기능들이 추가되었다.
- Default fall through due to missing break
- Multiple values per case not supported
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!
하나의 case
에는 하나의 값만 비교할 수 있다.
switch (itemCode) {
case 001:
case 002:
case 003:
System.out.println("It's an electronic gadget!");
}
- Supports multiple values per case
yield
is used to return a valueswitch
with arrows- scope
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;
}
Java 13부터는 yield
라는 키워드를 통해 switch
문이 값을 반환할 수 있게 되었다. 따라서 switch
문을 식expression으로도 사용이 가능하게 되었다. 그리고 yield
키워드가 값을 반환하면서 switch
문을 끝내기 때문에 break
은 더이상 사용할 필요가 없어졌다.
int val = switch (code) {
case "x", "y" :
yield 1;
case "z", "w" :
yield 2;
}
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!");
}
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;
}
}
while (expression) { statement; }
do { statement; } while (expression)
for (초기값; 조건; 방향&간격) { statement; }
for (<type> <instance>: <type-iterable>) { statement; }
while
, for
또는 switch
문을 끝낼 수 있는 구문이다.
loop문에서 continue
문이 실행되면 그 아래 코드들은 스킵한 뒤에 다음 스텝의 루프를 실행한다.
Guide to Control Flow Statements in Java
- 인텔리J, 이클립스, VS Code에서 JUnit 5로 테스트 코드 작성하는 방법에 익숙해 질 것.
- 이미 JUnit 알고 계신분들은 다른 것 아무거나!
- 더 자바, 테스트 강의도 있으니 참고하세요~
- 깃헙 이슈 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
인스턴스의login
을String
인스턴스로 반환받을 수 있다.
- 위 Github api의 클래스들을 활용해 각 댓글 작성자들이 어느 이슈에 댓글을 달았는지를
HashMap<String, Set<Integer>>
의 인스턴스에 작성자의 login과 이슈 번호들의 집합을 생성 - 반복문을 통해 1.에서 만든
HashMap
의 작성자를 키로 하는 value의 길이를 이슈 전체 길이로 나눠 작성자마다의 참여율 계산
Class for Github issue comments collecting
- node(vertex) 값value과 다음 노드의 위치next를 가지는 객체
- head LinkedList의 첫번째 node를 가리킨다.
- 각 node는 값value와 다음 노드로 연결되는 포인터(링크)next를 가진다.
- 노드의 종류는 head와 일반 원소가 되는 node가 있다.
- head는 값은 가지지 않으며 항상 LinkedList의 첫번째 node를 가리킨다.
- node는 다음 node가 없는 경우 null을 가리킨다.
public ListNode(int value)
- ListNode 인스터스의
this.value
에value
값을 할당한다.
- ListNode 인스터스의
ListNode add(ListNode head, ListNode nodeToAdd, int position)
를 구현하세요.- LinkedList의 head 노드를 파라미터로 받기 때문에
static
으로 선언한다. position-1
인덱스에 위치한 node의next
프로퍼티를nodeToAdd
로 바꾼다.nodeToAdd
의next
프로퍼티를position
인덱스에 위치한 node로 바꾼다.position
이 양수가 아니거나 LinkedList의 길이+1을 초과하면null
을 반환한다.
- LinkedList의 head 노드를 파라미터로 받기 때문에
ListNode remove(ListNode head, int positionToRemove)
를 구현하세요.- LinkedList의 head 노드를 파라미터로 받기 때문에
static
으로 선언한다. positionToRemove-1
인덱스에 위치한 node의next
프로퍼티를positionToRemove
인덱스에 위치한 node의next
로 바꾼다.positionToRemove
가 양수가 아니거나 LinkedList의 길이+1을 초과하면null
을 반환한다.
- LinkedList의 head 노드를 파라미터로 받기 때문에
boolean contains(ListNode head, ListNode nodeTocheck)
를 구현하세요.nodeToCheck
가null
이면return false
- 리스트의 각 노드의 주소값과
nodeToCheck
의 주소값을 비교한다. - 같은 게 있을 때
return true
- 리스트의 끝까지 같은게 없으면
return false
ListNode Implementation
ListNode Test
ListNode에서 static으로 선언된 메소드들을 LinkedList라는 객체의 메소드로 만들어 ListNode head
파라미터를 생략해 보았다.
LinkedList Implementation
LinkedList Test
- 길이가 동적인 컬렉션을 가진다.
- 가장 최근 input의 indextop를 알고있다.
public Stack()
int
배열을 가지는 Stack이기에int
배열의 사이즈를 초기에 정한다.this.top
의 값을 -1로 초기화한다.
void push(int data)
를 구현하세요.- 해당 사이즈를 초과하면 길이가 1이 더 늘어난 배열을 생성한다.
- 기존 스택의 값을 모두 복사한다.
- 새로운 값을 배열에 넣는다.
this.top
의 값을 1 증가 시킨다.
int pop()
을 구현하세요.- 길이가 0인 스택은
Exception
을 던진다. - 길이가 0이 아닌 스택은 배열의
this.top
인덱스에 위치한 값을 가져온다. this.top
의 값을 1 감소 시킨 후 가져온 값을 반환한다.
- 길이가 0인 스택은
Stack Implementation
Stack Test
public Stack()
ListNode
의head
를 만든다.
void push(int data)
를 구현하세요.data
를value
로 가지는ListNode
인스턴스를 만든다.- 1.에서 만든 인스턴스를 첫번째 노드로
add
한다.
int pop()
을 구현하세요.- 리스트의 길이가 0이면 Exception을 던진다.
- 리스트의 첫번째 노드의
value
를 가져온다. - 리스트의 head가 첫번째 노드의
next
를 가리키게 한다.
ListNodeStack Implementation
ListNodeStack Test
public Queue()
int
배열을 가지는 Queue이기에int
배열의 사이즈를 초기에 정한다.this.last
값을 -1로 초기화하여 Queue의 마지막 인덱스를 초기화한다.
void add(int data)
- 해당 사이즈를 초과하면 길이가 1이 더 늘어난 배열을 생성한다.
- 기존 큐의 값을 모두 복사한다.
- 새로운 값을 배열에 넣는다.
this.last
의 값을 1증가 시킨다.
int remove()
- 비어있는 큐인지 확인하여 비어있으면 Exception을 던진다.
- 큐의 배열의 첫번째 값을 가져온다.
- 배열의 모든 값들의 위치를 (원래 인덱스-1) 위치로 옮긴다.
this.last
의 값을 1 감소 시킨 후 가져온 값을 반환한다.
int peek()
- 비어있는 큐인지 확인하여 비어있으면 Exception을 던진다.
- 큐의 배열의 첫번째 값을 반환한다.
boolean isEmpty()
this.last
값이 -1이면returne true
- 아니면
return false
를 반환한다.
Queue Implementation
Queue Test
public ListNodeQueue()
- LinkedList의
head
를 만든다. this.last
값을 0으로 초기화하여 Queue의 마지막 인덱스를 초기화한다.
- LinkedList의
void add(int data)
data
를value
로 가지는ListNode
인스턴스를 만든다.this.last
를 1 증가시킨다.- 1.에서 만든 인스턴스를
this.last
인덱스에 위치한 노드로add
한다.
int remove()
- 비어있는 큐인지 확인하여 비어있으면 Exception을 던진다.
this.last
를 1 감소시킨다.- LinkedList의 첫번째 노드를
remove
하며value
를 반환한다.
int peek()
- 비어있는 큐인지 확인하여 비어있으면 Exception을 던진다.
- LinkedList의 첫번째 노드를 가져와
value
를 반환한다.
boolean isEmpty()
this.last
값이 0이면returne true
- 아니면
return false
를 반환한다.