## 22. Stack, Queue 자료구조 구현하기
- Stack과 Queue의 구동원리 이해 및 구현
- Stack 적용
- Prompt 클래스의 서브 클래스 MenuPrompt 정의
- MenuPrompt에서 Stack을 이용하여 프롬프트 제목에 breadcrumb 기능을 적용
- Queue 적용
- MenuPrompt 클래스에 메뉴 출력 기능을 추가
- App, BoardHandler, MemberHandler 변경
- MenuPrompt 클래스에 입력한 명령어의 history 기능을 추가
Stack과 Queue의 구동원리 이해 및 구현
ㄴ Stack 클래스 생성
Stack.java
ㄴ push => 목록 맨 끝에 추가하는 것
ㄴ LinkedList(상속 받은 메서드 = 서브 클래스에서 사용할 수 있는 수퍼 클래스)에 있는 add 를 이용하여 기능을 구현
ㄴ Member와 Student 클래스 생성하여 테스트
Member.java
ㄴ Member 클래스 작성
Student.java
ㄴ Member 클래스를 상속 받는 Student 클래스 작성
ㄴ 자바의 최상위 클래스인 Object 클래스에는 필드가 없음을 우측의 outline 을 통해 알 수 있음
ㄴ 해당 경로에 src.zip 파일이 위치함
=>
ㄴ src.zip 파일이 있음을 확인
=> src.zip 파일은 Java 개발 키트 (JDK) 라이브러리의 소스 코드를 포함하고 있으며, 일반적으로 JDK 설치와 함께 제공됨
=> 이 파일은 표준 Java 클래스와 라이브러리의 소스 코드에 대한 접근을 제공하여 개발자가 다양한 Java API의 구현 세부 정보를 살펴볼 수 있게 함
ㄴ Test 파일 생성
Test.java
ㄴ Student 클래스는 Member 클래스를 상속 받았으므로 Member 클래스의 변수도 사용 가능
Stack.java
ㄴ stack 의 크기가 0이면 null 을 리턴
Stack.java
ㄴ LinkedList 클래스의 remove(int index) 메서드를 사용
Stack.java
ㄴ this.size() 는 스택의 크기이므로 remove(int index) 메서드에는 index 에 해당하는 size() - 1 을 아규먼트로 받도록 함
=> 마지막 요소를 삭제하면서 반환
Stack.java
=>
Stack.java
ㄴ deletedValue 는 삭제하려는 요소이고 이름 삭제한 후 리턴
Stack.java
=>
ㄴ stack 클래스에서 main 을 생성하여 테스트
Stack 적용
ㄴ Prompt 클래스의 서브 클래스 MenuPrompt 정의
ㄴ Prompt 클래스의 서브 클래스인 MenuPrompt 를 생성
MenuPrompt.java
ㄴ breadcrumbs => "홈 > 카테고리 > 서브카테고리 > 현재페이지 " 와 같이 현재 위치를 시각적으로 표시하는 탐색 요소
MenuPrompt.java
ㄴ appendBreadcrumbs 는 title 을 push() 메서드를 이용해 넣고 breadcrumbs 를 pop() 메서드를 이용하여 삭제
MenuPrompt.java
=>
MenuPrompt.java
=>
ㄴ breadcrumbs : Stack 자료구조를 이용하여 현재 위치를 나타내는 경로를 저장
ㄴ 경로의 각 요소는 문자열로 표현됨
ㄴ appendBreadcrumbs 메소드를 통해 경로를 추가하고, removeBreadcrumbs 메소드를 통해 경로에서 마지막 요소를 제거
ㄴ appendBreadcrumbs(String title): 경로에 새로운 요소를 추가
ㄴ title은 추가할 경로 요소의 제목
ㄴ removeBreadcrumbs(): 경로에서 마지막 요소를 제거
ㄴ inputMenu(): 현재 위치를 나타내는 경로를 기반으로 메뉴 입력을 받음
MenuPrompt.java
ㄴ 경로가 "메인/회원"인 경우 "메인/회원>"을 반환함
Stack 적용
ㄴ MenuPrompt에서 Stack을 이용하여 프롬프트 제목에 breadcrumb 기능을 적용
App.java
ㄴ App 클래스에서 MenuPrompt 를 사용하기 위해 코드 추가
App.java
ㄴ MenuPrompt 클래스에 있는 appendBreadcrumbs 메서드에 "메인" 이라는 String 타입의 아규먼트를 전달해줌
App.java
ㄴ MenuPrompt 클래스에 있는 inputMenu 메서드를 이용
=> prompt.inputString("메인> "); 코드를 prompt.inputMenu() 로 변경
BoardHandler.java
ㄴ BoardHandler.java 에서 MenuPrompt 클래스를 사용하기 위해 코드 추가
BoardHandler.java
ㄴ Prompt -> MenuPrompt
BoardHandler.java
ㄴ execute() 실행 시 MenuPrompt 의 breadcrumbs 에 현재 메뉴 타이틀을 넣음
BoardHandler.java
=>
ㄴ App 클래스에서와 같이 inputString("%s> ", title); 대신 inputMenu() 메서드를 사용
=> ex) 메인/게시글>
BoardHandler.java
ㄴ 0 선택 시 Stack 에 있던 breadcrumbs pop() 되므로 ex) 메인/게시글> => 메인> 으로 변경되고 return을 만나 while 문을 나가서 App 클래스의 while 문으로 리턴됨
=> MemberHandler, ItemHandler 클래스도 마찬가지로 수정함
StringBuilder 사용해보기
MenuPrompt.java
=>
MenuPrompt.java
Queue 적용
MenuPrompt 클래스에 메뉴 출력 기능을 추가
ㄴ App, BoardHandler, MemberHandler 변경
ㄴ Queue 클래스 생성
Queue.java
ㄴ LinkedList 클래스의 add(value) 메서드를 이용한 offer(Object value) 메서드를 생성
ㄴ LinkedList 의 size() 와 remove(int index) 를 이용한 poll() 메서드를 생성
ㄴ size 가 0이면 null 을 리턴
ㄴ size 가 0보다 크면 해당 index 의 요소를 삭제
Queue.java
ㄴ Queue 클래스에 main 을 작성하여 테스트
Queue.java
ㄴ breadcrumbs 와 함께 menus 도 같이 받아오기 위해 선언
MenuPrompt.java
ㄴ menus 라는 이름으로 새로운 인스턴스를 생성하여 인스턴스명을 이용
ㄴ appendBreadcrumbs(String title, String menu) 메서드는 메뉴 경로와 해당 메뉴를 breadcrumbs 스택과 menus 스택에 추가하는 역할
ㄴ 메뉴 경로는 title 파라미터로 전달되고, 해당 메뉴는 menu 파라미터로 전달됨
ㄴ breadcrumbs.push(title)을 호출하여 메뉴 경로를 breadcrumbs 스택에 추가
ㄴ menus.push(menu)를 호출하여 해당 메뉴를 menus 스택에 추가
=> breadcrumbs 스택에는 이전 메뉴 경로들이 순서대로 쌓이고, menus 스택에는 이전 메뉴들이 순서대로 쌓이게 됨
MenuPrompt.java
ㄴ printMenu() 라는 메서드를 생성
ㄴ Stack 은 LinkedList 를 상속받았으므로 Stack 으로 인스턴스 변수 생성 시 인스턴스명을 통해 LinkedList 클래스의 get(int index) 메서드를 사용할 수 있음
ㄴ menus.size() 에서 - 1 을 해주는 이유는 index 는 개수보다 1개 작기 때문
ㄴ java.base > java.util > Stack 클래스에는 조회만을 위한 peek() 이라는 메소드 가 있음
=> 스택의 맨 위에서부터 하나씩 조회 가능
Stack.java
ㄴ Stack 클래스에 Object 타입의 조회를 위한 peek() 메서드 정의해주기
Stack.java
ㄴ empty() 메서드도 참고하여 정의하기
Stack.java
ㄴ this.size() == 0 => empty() 메서드 이용
MenuPrompt.java
ㄴ Stack 에 정의되어있는 peek() 메서드 이용
ㄴ printMenu() 메서드는 현재 메뉴의 제목을 출력함
ㄴ menus.peek()를 사용하여 menus 스택의 가장 위에 있는 요소를 가져와서 출력
=> peek() 메서드는 요소를 스택에서 제거하지 않고 가져오는 것이므로, 스택에서 요소가 제거되지 않고 현재 메뉴 제목만 출력됨
MenuPrompt.java
ㄴ removeBreadcrumbs() 메서드는 breadcrumbs 스택과 menus 스택에서 최근에 추가된 메뉴 경로와 메뉴를 제거하는 역할
ㄴ breadcrumbs.pop()을 호출하여 가장 위에 있는 메뉴 경로를 제거하고, menus.pop()을 호출하여 가장 위에 있는 메뉴를 제거
ㄴ 추가할 때 menu 도 같이 추가하므로 삭제 시에도 menus 도 같이 꺼내줘야함
=> 가장 최근에 추가된 메뉴 경로와 해당 메뉴가 제거되어 이전 메뉴 경로와 이전 메뉴로 돌아갈 수 있게 됨
App.java
ㄴ printMenu() => getMenu() 로 변경
App.java
ㄴ StringBuilder 사용하여 문자열 저장하여 리턴하기
MemberHandler.java
ㄴ printMenu() => getMenu() 로 변경 후 StringBuilder 이용
=> BoardHandler 클래스도 마찬가지로 변경해주기
App.java
ㄴ appendBreadcrumbs(String title, String menu) 메서드에 String 타입인 "메인" 과 getMenu() 메서드의 실행결과를 아규먼트로 넘겨줌
App.java
ㄴ MenuPrompt 클래스에 정의한 printMenu() 를 실행시킴
=> menu 를 하나씩 모두 조회하여 출력 (peek())
App.java
ㄴ MenuPrompt 클래스에 정의한 printMenu() 를 실행시킴
=> menu 를 하나씩 모두 조회하여 출력 (peek())
MemberHandler.java
ㄴ MenuPrompt 의 printMenu() 메서드를 실행해야 하므로 prompt 붙여주기
Queue 적용
MenuPrompt 클래스에 입력한 명령어의 history 기능을 추가
MenuPrompt.java
ㄴ 사용자가 입력한 명령어를 history 에 보관하기 위해 commandHistory 인스턴스 생성
MenuPrompt.java
ㄴ Queue 클래스의 offer(Object value) 메서드를 이용하여 사용자가 입력한 명령어를 history 에 보관
MenuPrompt.java
ㄴ command 라는 문자열 변수를 선언하고 여기에 titleBuilder 에 받은 값을 문자열로 변경하여 저장
ㄴ commandHistory 라는 Queue 인스턴스에 command 를 추가함
ㄴ 리턴값은 titleBuilder 에 받은 값을 문자열로 변경한 값
MenuPrompt.java
ㄴ commandHistory 에 사용자가 입력한 명령어가 10개 담겼다면 가장 처음에 들어간 값부터 삭제
=> Queue 의 poll() 메서드 이용
MenuPrompt.java
ㄴ 사용자가 입력한 commandHistory 를 모두 출력하는 printCommandHistory() 메서드 생성
MenuPrompt.java
ㄴ 사용자가 입력한 명령어를 모두 command 에 담는데, "history" 라는 문자열을 입력할 경우 printCommandHistory() 메서드를 실행하고 빈문자열을 리턴
ㄴ 그렇지 않다면 while(true) 문을 나감
MenuPrompt.java
ㄴ command 를 처음에는 null 로 선언
ㄴ 입력된 명령어가 "history" 가 되지 않는 이상 command 에 계속 저장됨
ㄴ 실행 결과 => "메뉴 번호가 옳지 않습니다" 가 출력돼서 아래처럼 코드 수정
MenuPrompt.java
ㄴ MenuPrompt 클래스의 inputMenu() 메서드 수정 (return ""; 제거)
ㄴ 잘 출력됨을 확인하였지만 숫자로만 출력돼서 어떤 메뉴인지 알기 힘듦 => 수정 필요
MenuPrompt.java
ㄴ 메뉴의 title 명을 알기위해 findMenuTitle 메서드 추가
MenuPrompt.java
ㄴ peek() 메서드의 리턴값이 Object 이므로 String 으로 형변환 필요
MenuPrompt.java
ㄴ 이를 통해 해당 메서드가 메뉴 타이틀을 가져온다는 것을 확인할 수 있음
MenuPrompt.java
ㄴ inputMenu() 메서드 에서 변수 수정 => menuTitle -> menuItem
MenuPrompt.java
ㄴ menuItem 변수에 command 에 해당하는 메뉴가 있는지 findMenuTitle(command) 메서드를 통해 그 메뉴 이름을, 없으면 null 을 리턴 받아 넣음
ㄴ 해당 리턴 값이 null 이 아니라면 commandHistory 에 Queue 의 offer(Object value) 메서드를 이용해서 다음과 같이 출력하도록 만듦 => 해당 menuItem 이 어떤 메뉴의 메뉴이름인지 알기 위함
ㄴ 해당 리턴 값이 null 이라면 command 그대로를 노출시킴
ㄴ 10개 이상이 되면 가장 처음에 들어갔던 값 부터 삭제됨
MenuPrompt.java
ㄴ "menu" 라는 문자열을 입력 받으면 printMenu() 메서드를 실행하라는 기능을 MenuPrompt 클래스에서 구현
App.java
ㄴ MemberHandler, BoardHandler, ItemHandler 도 마찬가지로 "menu" 라는 문자열을 입력하면 출력해주는 기능은 MenuPrompt 에서 다룸
MenuPrompt.java
ㄴ 메뉴 번호 유효성을 MenuPrompt 클래스에서 검사하도록 구현
=> App, MemberHandler, BoardHandler, ItemHandler 에 있는 해당 내용은 제거해줌 (MenuPrompt 에서 모두 처리 가능)
=> findMenuTitle -> findMenuItem 으로 메서드명 변경
App.java
=>
ㄴ if else 문 switch case 문으로 변경