4회차. 제어문

KIMA·2023년 1월 16일
1
post-thumbnail

목표

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

학습할 것

선택문(조건문)

: 조건식의 연산 결과에 따라 실행할 문장이 달라져서, 조건에 따라 프로그램의 실행 흐름을 변경할 수 있다.

  • 조건식의 연산 결과는 boolean 타입이어야 한다.
  • 종류 : if문, switch문
  • 처리할 경우의 수가 많을 경우에는 if문보다 switch문이 효율적이지만, switch문은 제약이 많다.

if문

: 가장 기본적인 조건문

if(조건식1) {
  // 조건식1이 true일 때, 실행될 문장들
}else if(조건식2) {
  // 조건식1이 false이고 조건식2가 true일 때, 실행될 문장들
}else {
  // 조건식1과 조건식2 모두 false일 때, 실행될 문장들
}
  • 중괄호안에 라인이 하나 뿐이라면, 중괄호를 생략할 수 있다.
    • 하지만, 나중에 라인이 추가될 것을 고려해서 되도록이면 적어주도록 하자.
  • 중첩 if문이 가능하다.

switch문

: if문에서 조건에 따라 분기해야 할 내용이 많아졌을 때 사용한다.

switch(조건식) {
  case1:
    // 조건식 == 값1 일 때, 실행될 문장들
    break; // switch문을 벗어난다.
  case2:
    // 조건식 == 값2 일 때, 실행될 문장들
    break;
  default:
    // 조건식의 결과와 일치하는 case문이 없을 때, 실행될 문장들
}
  • 제약 조건
    • 조건식의 결과는 정수 또는 문자열이어야 한다.
    • case문의 값은 정수 상수만 가능하며, 중복되지 않아야 한다.
  • 장점 : 가독성과 속도를 향상해준다.
  • 단점 : 제약이 많다.
  • 중첩 switch문이 가능하다.

새롭게 도입된 switch 연산자

  • 자바 12 버전부터 switch문에 대해 바뀐 부분이 있어 이에 대해 알아보자.

  • 기존 switch 문이다.

    int result;
    switch (str) {
      case "a":
        result = 1;
        break;
      case "b": case "c":
        result = 2;
        break;
      default:
        result = -1;
    }
  • 자바 12 버전 - ,(콤마)를 사용하여 여러 case를 한 줄에 나열한다.

    int result;
    switch (str) {
      case "a":
        result = 1;
        break;
      case "b", "c":
        result = 2;
        break;
      default:
        result = -1;
    }
  • 자바 12 버전 - switch operator가 람다식을 통해 결과를 반환할 수 있다.

    • switch fall through가 존재하지 않아 break를 쓰지 않아도 된다.
    int result = switch (str) {
      case "a" -> 1;
      case "b", "c" -> 2;
      default -> -1;
    };
  • 자바 13 버전 - switch operator가 yield 키워드를 사용하여 결과를 반환할 수 있다.

    • 람다식을 비롯하여 기존의 :를 이용한 switch문에서도 사용가능하다.
    int result = switch (str) {
      case "a"-> 1;
      case "b", "c" -> {
        System.out.println("{} 블록으로 멀티 라인 수행");
        yield 2;
      }
      default -> -1;
    };
    
    int result = switch (str) {
      case "a":
        yield 1;
      case "b", "c": {
        System.out.println("{} 블록으로 멀티 라인 수행");
        yield 2;
      }
      default:
        yield -1;
    };

반복문

: 어떤 작업이 반복적으로 수행되도록 할 때 사용된다.

  • 종류 : for, while, do-while
  • 무한 반복에 빠지지 않도록 주의한다.

for문

: 반복횟수를 알고 있을 때 사용한다.

for(변수초기화식; 조건식; 변수증감식) {
  // 조건식이 참일 때, 반복적으로 수행될 문장
}
  • 동작 과정
    1. 반복문에 사용될 변수를 초기화한다.
    2. 조건식이 참인 동안 조건식 -> 반복적으로 수행될 문장 -> 증감식이 반복된다.
    3. 조건식이 거짓이면 반복문이 종료된다.
  • 특징
    • 변수 초기화식, 조건식, 변수 증감식은 필수가 아니다.
    • 변수 초기화식, 조건식, 변수 증감식은 얼마든지 확장할 수 있다.

향상된 for문

: 반복문으로 배열과 컬렉션에 접근할 때, 좀 더 간편한 방법으로 처리할 수 있게 자바 5버전부터 추가된 문법이다.

for(변수타입 변수명 : 배열 또는 컬렉션) {
  // 반복적으로 수행될 문장
}
  • 동작 과정
    • 배열 또는 컬렉션에 저장된 값이 매 반복마다 하나씩 순서대로 읽혀져서 변수에 저장된다.
    • 블럭 안에는 해당 변수를 사용해서 코드를 작성한다.

while문

: 반복횟수를 모를 때 사용한다.

while(조건식) {
  // 조건식이 참일 때, 반복적으로 수행될 문장
}
  • 동작과정 : 조건이 거짓이 될 때까지 블럭 내의 문장을 반복한다.

do-while문

: while문과는 다르게 블럭안에 있는 문장들이 최소한 한 번은 수행된다.

{
  // 반복적으로 수행될 문장
} while(조건식);
  • 동작과정
    • 먼저 블럭을 한 번 수행한다.
    • 조건이 거짓이 될 때까지 블럭 내의 문장을 반복한다.

반복문에서 사용할 수 있는 키워드 : break와 continue

break

: 자신이 포함된 가장 가까운 반복문을 벗어난다.

int sum = 0;
int i = 0;

while(true) {
  i(sum > 100) break; // break문이 수행되면 while문을 완전히 벗어난다.
  ++i;
  sum += i;
}

continue

: 자신이 포함된 가장 가까운 반복문에서 다음 반복으로 넘어간다.

// 1 ~ 10수 중에 3의 배수를 제외하고 출력하는 코드
for(int i = 0; i <= 10; i++) {
  if(i % 3 == 0) {
    continue; // continue문이 수행되면 다음 반복으로 넘어간다.
  }
  System.out.println(i);
}

과제

과제 0. JUnit 5 학습

Jnuit이란?

: 자바에서 독립된 단위테스트를 지원해주는 프레임워크

JUnit 5?

아키텍처

: JUnit5에서는 이전 버전의 JUnit(단일 프로젝트)과는 다르게 3가지 하위 프로젝트의 여러 모듈로 구성되었다.

JUnit5

  • JUnit Platform : 테스트를 실행해주는 런처와 TestEngine API를 제공한다.
  • JUnit Jupiter : JUnit5를 지원하는 TestEngine API 구현체이다.
  • JUnit Vintage : JUnit4와 3을 지원하는 TestEngine 구현체이다.
    • JUnit5 플랫폼에서 JUnit4와 3 기반의 테스트 실행을 지원한다.

새로 생긴 것

  • 자바 8 버전 이상의 새로운 기능을 지원한다.
    • 람다식을 활용한 Assertion Method
  • 새로운 어노테이션
    • @TestFactory – 동적 테스트를위한 테스트 팩토리 인 메소드를 나타냅니다.
    • @DisplayName – 테스트 클래스 또는 테스트 메서드에 대한 사용자 지정 표시 이름을 정의합니다.
    • @Nested – 주석이 달린 클래스가 중첩 된 비 정적 테스트 클래스임을 나타냅니다.
    • @Tag – 테스트 필터링을위한 태그 선언
    • @ExtendWith – 사용자 지정 확장을 등록하는 데 사용됩니다.
    • @BeforeEach – 주석이 달린 메소드가 각 테스트 메소드 이전에 실행됨을 나타냅니다 (이전 @Before ).(여러번 비포)
    • @AfterEach – 각 테스트 메서드 (이전에는 @After ) 후에 주석이 추가 된 메서드가 실행됨을 나타냅니다.
    • @BeforeAll – 주석이 추가 된 메서드가 현재 클래스의 모든 테스트 메서드보다 먼저 실행됨을 나타냅니다 (이전 @BeforeClass ).(한번 통합전으로 전)
    • @AfterAll – 현재 클래스 (이전의 @AfterClass )의 모든 테스트 메서드 후에 주석이 추가 된 메서드가 실행됨을 나타냅니다.
    • @Disable – 테스트 클래스 또는 메서드를 비활성화하는 데 사용됩니다 (이전에는 @Ignore ).

의존성 설정

  • 스프링 부트 2.2 이상 버전의 프로젝트를 만들면 기본적으로 JUnit5 의존성이 추가되어있다.
  • 그 외에는 의존성을 추가해준다.
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.7.0</version>
        <scope>test</scope>
    </dependency>
    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.7.0'
  • 자바 8 버전 이상이 필요하다.

어노테이션

  • @Test
    : 단위 테스트 메서드에 선언하는 것으로, 독립적으로 테스트를 수행한다.

    • 테스트 메서드 구성요소
      • Arrange : 테스트 환경 조성
        • 예) 테스트 대상 객체 생성
      • Act : 테스트 실행
      • Assert : Assert문을 이용해 결과 비교
    • 테스트 메서드 명명 규칙 : test_메서드이름_조건_예상결과
        • isAdult_AgeLessThan18_False
        • withdrawMoney_InvalidAccount_ExceptionThrown
    • 테스트 클래스 안의 단위 테스트 메서드들이 각각 호출될 때마다 테스트 클래스의 새로운 인스턴스를 생성하여 테스트 메서드들이 독립적인 환경에서 단위 테스트가 이루어지게 한다.
    • JUnit4와 다르게 속성을 선언하지 않는다.
  • 테스트 라이프 사이클 관리
    JUnit5 LifeCycle

    • @BeforeAll / @BeforeClass, @AfterAll / @AfterClass
      : 테스트 클래스 실행 전과 후에 동작할 메서드 위에 선언한다.

      • 메서드를 static으로 선언한다.
        • 테스트 클래스 안의 단위 테스트 메서드들이 각각 호출될 때마다 테스트 클래스의 새로운 인스턴스를 생성하여 테스트 메서드들이 독립적인 환경에서 단위 테스트가 이루어지게 하기 때문에
      • 용도
        • DB연결
        • DB 초기화
        • 드라이버 로딩
    • @BeforeEach / @Before, @AfterEach / @After
      : 각 테스트 메서드가 실행되기 전과 후에 동작할 메서드위에 선언한다.

      • @Before 용도
        • 테스트 대상 객체 생성
      • @After 용도
        • 단위 테스트간 데이터 침범을 막기 위해 사용
  • @Disabled
    : 테스트 클래스 또는 테스트 메서드를 비활성화한다.

  • @DisplayNameGeneration
    : 테스트 실행 결과에서 보이는 테스트 클래스 혹은 메서드 표시 이름 생성기를 선언한다.

    • 생성기 안에서는 MethodClass 레퍼런스 정보를 활용하여 표시 이름을 생성한다.
    • 기본 구현체 : DisplayNameGeneratorReplaceUnderscores
  • @DisplayName
    : 테스트 실행 결과에서 보이는 테스트 클래스 혹은 메서드 표시 이름을 직접 지정한다.

    • 어떤 일을 수행하는 테스트인지 보다 쉽게 표현할 수 있다.
    • @DisplayNameGeneration보다 우선순위가 높다.

Assertion

: 테스트 케이스의 수행 결과를 판별함

종류

  • assertEquals(expected, actual(, delta))
    : 실제 값이 기대한 값과 같은지
    • 객체의 경우 객체의 값을 비교함
    • delta 인자 : 두 실수값이 delta 범위 내에서 같은지 테스트
  • assertSame(obj1, obj2) / assertNotSame(obj1, obj2)
    : 두 객체가 같은 참조인지
  • assertArrayEquals(arr1, arr2)
    : 두 배열이 일치한지
  • assertTrue((message,) boolean) / assertFalse(boolean)
    • message : true이면 message를 표시
    • fail(message) : 테스트 결과를 실패로 만든다.
  • assertNull(obj) / assertNotNull(obj)
  • assertAll((heading, )executables...)
    : 모든 확인 구문 확인
    • executable : assert문
    • heading :executable 주제
  • assertThrows(expectedType, executable)
    : 특정 예외가 발생됐는지 확인
    • executable : assert문
  • assertTimeout(duration)duration, executable)
    : 특정 시간 안에 실행이 완료되는지 확인
    • executable : assert문

Hamcrest Assertion

: Matcher 라이브러리 중 하나로서, 테스트 표현식을 작성할 때 문맥적으로 자연스러운 문장을 만들어준다.

  • Matcher 라이브러리 : 필터나 검색등을 위해 값을 비교할 때 좀 더 편리하게 사용하도록 도와주는 라이브러리
  • 또한, JUnit 단정문에 비해 오류 메시지 가독성이 좋다.
  • 문법 : assertThat(expected, matchers)
  • JUnit보다는 assertjassertThat() 사용을 추천한다.
    • 문법 : assertThat(expected).matcher1().matcher2() ...
    • 메서드 체이닝을 지원해, 가독성이 좋다.
    • CoreMatchers와 달리 추가적으로 라이브러리가 필요하지 않다.
    • 자동 완성을 확실하게 지원한다.
  • matchers
    1. equalTo(value | matcher) - 동일할 경우 성공
    2. is(value | matcher) - equalTo와 동일하나 가독성 증진
    3. not(matcher1, …) - 조건에 사용된 matcher의 결과와 맞지않는지
    4. allOf(matcher1, matcher2, ...) - 조건에 사용된 matcher가 모두 통과되는지
    5. anyOf(matcher1, matcher2, ...) - 조건에 사용된 matcher 중 하나만이라도 통과되는지
    6. containsInAnyOrder(value, …) - 순서에 상관없이 지정해준 value들을 모두 포함하는지
    7. instanceOf, isCompatibleType - 타입
    8. notNullValue, nullValue - null값 여부
    9. sameInstance - 두 Object가 같은지
    10. hasEntry, hasKey, hasValue - Map요소에대해 포함여부
    11. hasItem(item | Matcher), hasItems - collection 에 item 혹은 조건을 만족하는 item 포함여부
    12. everyItem(Matcher) - 모든 item이 해당 조건을 만족하는지
    13. hasItemInArray - 배열에 해당 item이 존재하는지
    14. closeTo - 부동소수점 값에 대한 허용근사치내 해당하는지
    15. greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo - >. >=, <, <=
    16. hasToString(string) - 해당 문자열과 완전 같은지
    17. equalToIgnoringCase - 대소문자가 달라도 같은것으로 판단하여 비교
    18. equalToIgnoringWhiteSpace - 공백을 제거한 상태에서 두값이 같은지 비교
    19. containsString, endsWith, startsWith - 문자열의일부, 시작, 끝나는부분에 대한 비교
    20. hasSize(size) - 객체의 크기가 size인지
    21. empty - 비었는지 확인
    22. hasProperty(property) - 객체내에 해당 속성이 포함되어 있는지
    23. samePropertyValuesAs(object2) - 두 객체의 property와 value가 같은지
    24. anything - 어느 값이 오던 pass, 즉, 값을 비교하는 것이 아닌 이 코드가 에러가 없는지 확인할 때 사용

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

live-study 대시 보드 요구사항

  • 깃헙 이슈 1번부터 18번까지 댓글을 순회하며 댓글을 남긴 사용자를 체크할 것.
  • 참여율을 계산하기. 총 18회 중에 몇 %를 참여했는지 소숫점 두 자리까지 보여줄 것.
  • (깃헙 자바 라이브러리)[https://github-api.kohsuke.org/] 사용하면 편리함.

코드

import org.kohsuke.github.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {
    private static final String REPOSITORY_PATH = "whiteship/live-study";
    private static final String TOKEN = "personal_access_token";
    private static final int COUNT_WEEK = 15;

    public static void main(String[] args) throws IOException {
        // Personal access token을 통해 깃헙에 연결
        // Personal access token은 깃헙에서 생성 가능
        GitHub github = new GitHubBuilder().withOAuthToken(TOKEN).build();

        // 레포지토리 접근
        GHRepository repository = github.getRepository(REPOSITORY_PATH);

        Map<String, int[]> participant = getParticipant(repository);
        printParticipant(participant);
    }

    private static Map<String, int[]> getParticipant(GHRepository repository) throws IOException {
        // 참가자 맵
        // key : user name, value : participation counting every week
        Map<String, int[]> participant = new HashMap<>();

        // 이슈 순회
        for (int i = 1; i <= COUNT_WEEK; i++) {
            GHIssue ghIssue = repository.getIssue(i);
            // 댓글 순회
            List<GHIssueComment> comments = ghIssue.getComments();
            for (GHIssueComment comment :
                    comments) {
                String userName = comment.getUser().getLogin();

                if (!participant.containsKey(userName)) {
                    participant.put(userName, new int[COUNT_WEEK + 1]);
                }
                int[] countParticipationEveryWeek = participant.get(userName);
                countParticipationEveryWeek[i]++;
            }
        }

        return participant;
    }

    private static void printParticipant(Map<String, int[]> participant) {
        participant.forEach((key, value) -> {
            int countIsParticipateEveryWeek = 0;
            for (int countParticipation :
                    value) {
                if (countParticipation > 0) countIsParticipateEveryWeek++;
            }
            System.out.printf("%-20s의 참여율은 %.2f%%입니다.%n", key, (countIsParticipateEveryWeek / (double) COUNT_WEEK) * 100);
        });
    }
}

결과

kimzerovirus        의 참여율은 6.67%입니다.
KwangJongJeon       의 참여율은 73.33%입니다.
jessi68             의 참여율은 13.33%입니다.
ufonetcom           의 참여율은 33.33%입니다.
JIN-096             의 참여율은 80.00%입니다.
ssonsh              의 참여율은 100.00%입니다.
DominicStrength     의 참여율은 6.67%입니다.
Ohzzi               의 참여율은 86.67%입니다.
dongsub-joung       의 참여율은 13.33%입니다.
moo1o               의 참여율은 6.67%입니다.
Azderica            의 참여율은 100.00%입니다.
jymaeng95           의 참여율은 100.00%입니다.
ggomjae             의 참여율은 6.67%입니다.
binghe819           의 참여율은 20.00%입니다.
fpdjsns             의 참여율은 60.00%입니다.
...

과제2. LinkedList 구현

LinkedList란?

: 노드들을 포인터로 연결한 자료구조

  • 노드는 값과 다음 값을 가리키는 포인터로 구성되어 있다.
  • Head포인터는 첫번째 노드를 뜻한다.
  • 값에 접근하려면 Head 포인터부터 순서대로 접근하므로 속도가 느리다.
  • 포인터로 연결되어 있으므로 데이터를 삽입하거나 삭제하는 연산 속도가 빠르다.
  • 배열과는 다르게 선언할 때 크기를 별도로 지정하지 않아도 된다.
  • 종류
    • 싱글 연결 리스트 : next 포인터만 가진다.
    • 이중 연결 리스트 : next 포인터와 prev 포인터를 가진다.
    • 원형 이중 연결 리스트 : 이중 연결 리스트와 같지만 마지막 노드의 next 포인터가 헤드 노드를 가리킨다.

LinkedList 구현

정수를 저장하는 ListNode

import java.util.Objects;

public class ListNode {
    private int data;
    private ListNode next;

    public ListNode(int data) {
        this.data = data;
        this.next = null;
    }

    public int getData() {
        return data;
    }

    public ListNode next() {
        return next;
    }

    public ListNode linking(ListNode node) {
        next = node;
        return next;
    }

    public boolean hasNext() {
        return Objects.nonNull(next);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ListNode listNode = (ListNode) o;
        return data == listNode.data && Objects.equals(next, listNode.next);
    }

    @Override
    public int hashCode() {
        return Objects.hash(data, next);
    }

    @Override
    public String toString() {
        return String.valueOf(data);
    }
}

LinkedList

public interface LinkedList {
    ListNode add(ListNode head, ListNode nodeToAdd, int position);

    ListNode remove(ListNode head, int positionToRemove);

    boolean contains(ListNode head, ListNode nodeToCheck);

    void print(ListNode head);
}
import java.util.Objects;

public class LinkedListImpl implements LinkedList {

    @Override
    public ListNode add(ListNode head, ListNode nodeToAdd, int position) {
        if (position == 0) {
            if (head == null) {
                return nodeToAdd;
            }
            nodeToAdd.linking(head);
            head = nodeToAdd;
            return head;
        }
        ListNode node = head;
        for (int i = 0; i < position - 1; i++) {
            if (Objects.isNull(node)) throw new IllegalArgumentException();
            node = node.next();
        }
        nodeToAdd.linking(node.next());
        node.linking(nodeToAdd);
        return head;
    }

    @Override
    public ListNode remove(ListNode head, int positionToRemove) {
        if (positionToRemove == 0) {
            if (Objects.isNull(head)) throw new IllegalArgumentException();
            head = head.next();
        } else {
            ListNode node = head;
            for (int i = 0; i < positionToRemove - 1; i++) {
                if (Objects.isNull(node)) throw new IllegalArgumentException();
                node = node.next();
            }
            if(Objects.isNull(node.next())) throw new IllegalArgumentException();
            node.linking(node.next().next());
        }

        return head;
    }

    @Override
    public boolean contains(ListNode head, ListNode nodeToCheck) {
        ListNode node = head;

        while (!Objects.isNull(node)) {
            if (node.getData() == nodeToCheck.getData()) {
                return true;
            }
            node = node.next();
        }
        return false;
    }

    @Override
    public void print(ListNode head) {
        ListNode node = head;
        while (Objects.nonNull(node)) {
            System.out.print(node);
            node = node.next();
        }
    }

    public int size(ListNode head) {
        if (Objects.isNull(head)) return 0;

        ListNode current = head;
        int size = 1;

        while (current.hasNext()) {
            size++;
            current = current.next();
        }

        return size;
    }
}

과제3. int 배열을 사용해서 정수를 저장하는 Stack 구현

public interface Stack {
    boolean isEmpty();

    void push(int data);

    int pop();

    void print();
}
import java.util.EmptyStackException;

public class ArrayStack implements Stack {
    private int top;
    private int stackSize;
    private int[] stackArr;

    public ArrayStack(int stackSize) {
        top = -1;
        this.stackSize = stackSize;
        stackArr = new int[stackSize];
    }

    @Override
    public boolean isEmpty() {
        return top == -1;
    }

    public boolean isFull() {
        return top == stackSize - 1;
    }

    @Override
    public void push(int data) {
        if(isFull()) throw new StackOverflowError();
        stackArr[++top] = data;
    }

    @Override
    public int pop() {
        if(isEmpty()) {
            throw new EmptyStackException();
        }
        int data = stackArr[top];
        top--;
        return data;
    }

    @Override
    public void print() {
        final StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < top; i++) {
            int data = stackArr[i];
            sb.append(data + ", ");
        }
        sb.append(stackArr[top]).append(']');
        System.out.println(sb);
    }
}

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

public interface Stack {
    boolean isEmpty();

    void push(int data);

    int pop();

    void print();
}
import linkedlist.LinkedListImpl;
import linkedlist.ListNode;

import java.util.EmptyStackException;

public class ListNodeStack implements Stack {
    private final LinkedListImpl linkedList = new LinkedListImpl();
    private ListNode top;

    @Override
    public boolean isEmpty() {
        return linkedList.size(top) == 0;
    }

    @Override
    public void push(int data) {
        top = linkedList.add(top, new ListNode(data), 0);
    }

    @Override
    public int pop() {
        if(isEmpty()) {
            throw new EmptyStackException();
        }
        int data = top.getData();
        top = linkedList.remove(top, 0);
        return data;
    }

    @Override
    public void print() {
        linkedList.print(top);
    }
}

과제 5. Queue 구현

public interface Queue {
    void add(int data);

    int remove() throws Exception;

    int peek() throws Exception;

    boolean isEmpty();
}

배열을 사용

public class ArrayQueue implements Queue {
    private static final int LENGTH_INTERVAL = 1;
    private int[] array;
    private int front;

    public ArrayQueue() {
        this.array = new int[0];
        this.front = -1;
    }

    @Override
    public void add(int data) {
        front += 1;
        if (array.length == front) {
            int[] temp = new int[array.length + LENGTH_INTERVAL];
            for (int i = 0; i < array.length; i++) {
                temp[i] = array[i];
            }

            temp[front] = data;
            array = temp;
        } else {
            array[front] = data;
        }
    }

    @Override
    public int remove() throws Exception {
        if (isEmpty()) {
            throw new Exception("No more queue");
        }
        int data = array[0];
        for (int i = 1; i <= this.front; i++) {
            array[i - 1] = array[i];
        }
        front -= 1;
        return data;
    }

    @Override
    public int peek() throws Exception {
        if (isEmpty()) {
            throw new Exception("No more queue");
        }
        return array[0];
    }

    @Override
    public boolean isEmpty() {
        if (this.front == -1) {
            return true;
        } else {
            return false;
        }
    }
}

ListNode를 사용

import linkedlist.LinkedListImpl;
import linkedlist.ListNode;

public class ListNodeQueue implements Queue{
    private final LinkedListImpl linkedList = new LinkedListImpl();
    private ListNode head;
    private int last;

    @Override
    public void add(int data) {
        ListNode node = new ListNode(data);
        head = linkedList.add(head, node, last);
        last++;
    }

    @Override
    public int remove() throws Exception {
        if (isEmpty()) {
            throw new Exception("No more queue");
        }
        int data = head.getData();
        head = linkedList.remove(head, 0);
        last--;

        return data;
    }

    @Override
    public int peek() throws Exception {
        if (isEmpty()) {
            throw new Exception("No more queue");
        }
        return head.getData();
    }

    @Override
    public boolean isEmpty() {
        return last == 0;
    }

    public void print() {
        linkedList.print(head);
    }
}

Reference

profile
안녕하세요.

0개의 댓글